1- cdef enum :
1+ cdef enum :
22 __PREALLOCED_BUFS = 4
33
44
@@ -341,13 +341,13 @@ cdef class UVStream(UVBaseTransport):
341341 else :
342342 self .__reading_stopped()
343343
344- cdef inline _try_write(self , object data):
344+ cdef inline Py_ssize_t _try_write(self , object data) except ? - 2 :
345345 cdef:
346- ssize_t written
346+ Py_ssize_t written
347347 bint used_buf = 0
348348 Py_buffer py_buf
349349 void * buf
350- size_t blen
350+ Py_ssize_t blen
351351 int saved_errno
352352 int fd
353353
@@ -368,6 +368,8 @@ cdef class UVStream(UVBaseTransport):
368368 blen = py_buf.len
369369
370370 if blen == 0 :
371+ if used_buf:
372+ PyBuffer_Release(& py_buf)
371373 # Empty data, do nothing.
372374 return 0
373375
@@ -392,24 +394,20 @@ cdef class UVStream(UVBaseTransport):
392394 PyBuffer_Release(& py_buf)
393395
394396 if written < 0 :
395- if saved_errno == errno.EAGAIN or \
396- saved_errno == system.EWOULDBLOCK:
397- return - 1
397+ if saved_errno in (errno.EAGAIN, system.EWOULDBLOCK):
398+ return 0
398399 else :
399400 exc = convert_error(- saved_errno)
400401 self ._fatal_error(exc, True )
401- return
402+ return - 1
402403
403404 if UVLOOP_DEBUG:
404405 self ._loop._debug_stream_write_tries += 1
405406
406- if < size_t> written == blen:
407- return 0
408-
409407 return written
410408
411409 cdef inline _buffer_write(self , object data):
412- cdef int dlen
410+ cdef Py_ssize_t dlen
413411
414412 if not PyBytes_CheckExact(data):
415413 data = memoryview(data).cast(' b' )
@@ -421,22 +419,20 @@ cdef class UVStream(UVBaseTransport):
421419 self ._buffer_size += dlen
422420 self ._buffer.append(data)
423421
424- cdef inline _initiate_write(self , bint skip_fast_path ):
425- if ( not skip_fast_path and
426- not self ._protocol_paused and
427- ( < uv.uv_stream_t * > self ._handle).write_queue_size == 0 and
428- self ._buffer_size > self ._high_water ):
422+ cdef inline _initiate_write(self ):
423+ cdef bint all_sent
424+
425+ if ( not self ._protocol_paused and
426+ ( < uv.uv_stream_t * > self ._handle).write_queue_size == 0 ):
429427 # Fast-path. If:
430- # - the caller hasn't tried fast path itself
431428 # - the protocol isn't yet paused,
432429 # - there is no data in libuv buffers for this stream,
433- # - the protocol will be paused if we continue to buffer data
434430 #
435431 # Then:
436432 # - Try to write all buffered data right now.
437433 all_sent = self ._exec_write()
438434 if UVLOOP_DEBUG:
439- if self ._buffer_size != 0 or self ._buffer ! = [] :
435+ if self ._buffer_size != 0 or self ._buffer:
440436 raise RuntimeError (
441437 ' _buffer_size is not 0 after a successful _exec_write' )
442438
@@ -452,20 +448,21 @@ cdef class UVStream(UVBaseTransport):
452448 self ._maybe_pause_protocol()
453449 self ._loop._queue_write(self )
454450
455- cdef inline _exec_write(self ):
451+ cdef inline bint _exec_write(self ) except ? - 1 :
456452 cdef:
457453 int err
458- int buf_len
454+ Py_ssize_t buf_len
455+ Py_ssize_t sent
459456 _StreamWriteContext ctx = None
460457
461458 if self ._closed:
462459 # If the handle is closed, just return, it's too
463460 # late to do anything.
464- return
461+ return False
465462
466463 buf_len = len (self ._buffer)
467464 if not buf_len:
468- return
465+ return True
469466
470467 if (< uv.uv_stream_t* > self ._handle).write_queue_size == 0 :
471468 # libuv internal write buffers for this stream are empty.
@@ -475,34 +472,16 @@ cdef class UVStream(UVBaseTransport):
475472 data = self ._buffer[0 ]
476473 sent = self ._try_write(data)
477474
478- if sent is None :
479- # A `self._fatal_error` was called.
480- # It might not raise an exception under some
481- # conditions.
482- self ._buffer_size = 0
483- self ._buffer.clear()
484- if not self ._closing:
485- # This should never happen.
486- raise RuntimeError (
487- ' stream is open after UVStream._try_write '
488- ' returned None' )
489- return
490-
491- if sent == 0 :
492- # All data was successfully written.
475+ if sent == len (data):
476+ # The most likely outcome,
477+ # all data was successfully written.
493478 self ._buffer_size = 0
494479 self ._buffer.clear()
495480 # on_write will call "maybe_resume_protocol".
496481 self ._on_write()
497482 return True
498483
499- if sent > 0 :
500- if UVLOOP_DEBUG:
501- if sent == len (data):
502- raise RuntimeError (
503- ' _try_write sent all data and returned '
504- ' non-zero' )
505-
484+ elif sent > 0 :
506485 if PyBytes_CheckExact(data):
507486 # Cast bytes to memoryview to avoid copying
508487 # data that wasn't sent.
@@ -512,6 +491,19 @@ cdef class UVStream(UVBaseTransport):
512491 self ._buffer_size -= sent
513492 self ._buffer[0 ] = data
514493
494+ elif sent == - 1 :
495+ # A `self._fatal_error` was called.
496+ # It might not raise an exception under some
497+ # conditions.
498+ self ._buffer_size = 0
499+ self ._buffer.clear()
500+ if not self ._closing:
501+ # This should never happen.
502+ raise RuntimeError (
503+ ' stream is open after UVStream._try_write '
504+ ' returned None' )
505+ return False
506+
515507 # At this point it's either data was sent partially,
516508 # or an EAGAIN has happened.
517509
@@ -545,15 +537,15 @@ cdef class UVStream(UVBaseTransport):
545537 self ._fatal_error(ex, True )
546538 self ._buffer.clear()
547539 self ._buffer_size = 0
548- return
540+ return False
549541
550542 elif err != uv.UV_EAGAIN:
551543 ctx.close()
552544 exc = convert_error(err)
553545 self ._fatal_error(exc, True )
554546 self ._buffer.clear()
555547 self ._buffer_size = 0
556- return
548+ return False
557549
558550 # fall through
559551
@@ -577,9 +569,10 @@ cdef class UVStream(UVBaseTransport):
577569
578570 exc = convert_error(err)
579571 self ._fatal_error(exc, True )
580- return
572+ return False
581573
582574 self ._maybe_resume_protocol()
575+ return False
583576
584577 cdef size_t _get_write_buffer_size(self ):
585578 if self ._handle is NULL :
@@ -684,46 +677,8 @@ cdef class UVStream(UVBaseTransport):
684677 self ._conn_lost += 1
685678 return
686679
687- cdef ssize_t bytes_written
688-
689- if self ._get_write_buffer_size() == 0 :
690- bytes_written_ = self ._try_write(buf)
691-
692- if bytes_written_ is None :
693- # A `self._fatal_error` was called.
694- # It might not raise an exception under some
695- # conditions.
696- if not self ._closing:
697- raise RuntimeError (' stream is open after '
698- ' UVStream._try_write returned None' )
699-
700- return
701-
702- bytes_written = bytes_written_
703-
704- if bytes_written == 0 :
705- # All data was successfully written.
706- # on_write will call "maybe_resume_protocol".
707- return
708-
709- if bytes_written > 0 :
710- if UVLOOP_DEBUG:
711- if bytes_written == len (buf):
712- raise RuntimeError (' _try_write sent all data and '
713- ' returned non-zero' )
714-
715- if PyBytes_CheckExact(buf):
716- # Cast bytes to memoryview to avoid copying
717- # data that wasn't sent.
718- buf = memoryview(buf)
719- buf = buf[bytes_written_:]
720-
721- # At this point it's either data was sent partially,
722- # or an EAGAIN has happened.
723- # buffer remaining data and send it later
724-
725680 self ._buffer_write(buf)
726- self ._initiate_write(True ) # skip fast path in _initiate_write
681+ self ._initiate_write()
727682
728683 def writelines (self , bufs ):
729684 self ._ensure_alive()
@@ -735,7 +690,7 @@ cdef class UVStream(UVBaseTransport):
735690 return
736691 for buf in bufs:
737692 self ._buffer_write(buf)
738- self ._initiate_write(False ) # try fast path in _initiate_write
693+ self ._initiate_write()
739694
740695 def write_eof (self ):
741696 self ._ensure_alive()
0 commit comments