Esempio n. 1
0
 /**
  * [COROUTINE] Write data to this stream.
  *
  * Execution of the current strand is suspended until the data is sent.
  *
  * Write operations must be exclusive. If concurrent writes are attempted a
  * StreamLockedException is thrown.
  *
  * @param string       $buffer The data to write to the stream.
  * @param integer|null $length The maximum number of bytes to write.
  *
  * @return integer               The number of bytes written.
  * @throws StreamClosedException if the stream is already closed.
  * @throws StreamLockedException if concurrent writes are unsupported.
  * @throws StreamWriteException  if an error occurs while writing to the stream.
  */
 public function write($buffer, $length = null)
 {
     if ($this->strand) {
         throw new StreamLockedException();
     } elseif ($this->isClosed()) {
         throw new StreamClosedException();
     }
     (yield Recoil::suspend(function ($strand) {
         $this->strand = $strand;
         $strand->kernel()->eventLoop()->addWriteStream($this->stream, function ($stream, $eventLoop) use($strand) {
             $eventLoop->removeWriteStream($this->stream);
             $this->strand->resumeWithValue(null);
         });
     }));
     $this->strand = null;
     $exception = null;
     set_error_handler(function ($code, $message, $file, $line) use(&$exception) {
         $exception = new ErrorException($message, 0, $code, $file, $line);
     });
     $bytesWritten = fwrite($this->stream, $buffer, $length ?: strlen($buffer));
     restore_error_handler();
     if (false === $bytesWritten) {
         throw new StreamWriteException($exception);
     }
     (yield Recoil::return_($bytesWritten));
     // @codeCoverageIgnoreStart
 }
Esempio n. 2
0
 /**
  * [COROUTINE] Read data from the stream.
  *
  * Execution of the current strand is suspended until data is available or
  * the end of the data stream is reached.
  *
  * Read operations must be exclusive. If concurrent reads are attempted a
  * StreamLockedException is thrown.
  *
  * @param integer $length The maximum number of bytes to read.
  *
  * @return string                The data read from the stream.
  * @throws StreamClosedException if the stream is already closed.
  * @throws StreamLockedException if concurrent reads are unsupported.
  * @throws StreamReadException   if an error occurs while reading from the stream.
  */
 public function read($length)
 {
     if ($this->strand) {
         throw new StreamLockedException();
     } elseif ($this->isClosed()) {
         throw new StreamClosedException();
     }
     (yield Recoil::suspend(function ($strand) {
         $this->strand = $strand;
         $strand->kernel()->eventLoop()->addReadStream($this->stream, function ($stream, $eventLoop) {
             $eventLoop->removeReadStream($stream);
             $this->strand->resumeWithValue(null);
         });
     }));
     $this->strand = null;
     $exception = null;
     set_error_handler(function ($code, $message, $file, $line) use(&$exception) {
         $exception = new ErrorException($message, 0, $code, $file, $line);
     });
     $buffer = fread($this->stream, $length);
     restore_error_handler();
     if (is_resource($this->stream) && feof($this->stream)) {
         fclose($this->stream);
     }
     if (false === $buffer) {
         throw new StreamReadException($exception);
     }
     (yield Recoil::return_($buffer));
     // @codeCoverageIgnoreStart
 }
Esempio n. 3
0
 /**
  * [COROUTINE] Read a value from this channel.
  *
  * Execution of the current strand is suspended until a value is available.
  *
  * If the channel is already closed, or is closed while a read operation is
  * pending a ChannelClosedException is thrown.
  *
  * @return mixed                  The value read from the channel.
  * @throws ChannelClosedException if the channel has been closed.
  */
 public function read()
 {
     if ($this->isClosed()) {
         throw new ChannelClosedException();
     }
     $value = (yield Recoil::suspend(function ($strand) {
         $this->readStrands->push($strand);
         if (!$this->writeStrands->isEmpty()) {
             $writeStrand = $this->writeStrands->dequeue();
             $writeStrand->resumeWithValue(null);
         }
     }));
     (yield Recoil::return_($value));
     // @codeCoverageIgnoreStart
 }
Esempio n. 4
0
 /**
  * [COROUTINE] Read a value from this channel.
  *
  * Execution of the current strand is suspended until a value is available.
  *
  * If the channel is already closed, or is closed while a read operation is
  * pending a ChannelClosedException is thrown.
  *
  * Read operations must be exclusive only if the underlying stream requires
  * exclusive reads.
  *
  * @return mixed                  The value read from the channel.
  * @throws ChannelClosedException if the channel has been closed.
  * @throws ChannelLockedException if concurrent reads are unsupported.
  */
 public function read()
 {
     while (!$this->unserializer->hasValue()) {
         try {
             $buffer = (yield $this->stream->read($this->bufferSize));
         } catch (StreamClosedException $e) {
             throw new ChannelClosedException($e);
         } catch (StreamLockedException $e) {
             throw new ChannelLockedException($e);
         }
         $this->unserializer->feed($buffer);
         if ($this->stream->isClosed()) {
             $this->unserializer->finalize();
         }
     }
     (yield Recoil::return_($this->unserializer->unserialize()));
     // @codeCoverageIgnoreStart
 }
Esempio n. 5
0
 /**
  * [COROUTINE] Write data to this stream.
  *
  * Execution of the current strand is suspended until the underlying stream
  * is drained.
  *
  * Write operations must be exclusive. If concurrent writes are attempted a
  * StreamLockedException is thrown.
  *
  * @param string       $buffer The data to write to the stream.
  * @param integer|null $length The maximum number of bytes to write.
  *
  * @return integer               The number of bytes written.
  * @throws StreamClosedException if the stream is already closed.
  * @throws StreamLockedException if concurrent writes are unsupported.
  * @throws StreamWriteException  if an error occurs while writing to the stream.
  */
 public function write($buffer, $length = null)
 {
     if ($this->strand) {
         throw new StreamLockedException();
     } elseif ($this->isClosed()) {
         throw new StreamClosedException();
     }
     if (null === $length) {
         $length = strlen($buffer);
     } else {
         $buffer = substr($buffer, 0, $length);
     }
     (yield Recoil::suspend(function ($strand) use($buffer) {
         $this->strand = $strand;
         if ($this->stream->write($buffer)) {
             $this->onStreamDrain();
         }
     }));
     $this->strand = null;
     (yield Recoil::return_($length));
     // @codeCoverageIgnoreStart
 }
Esempio n. 6
0
 /**
  * [COROUTINE] Read data from the stream.
  *
  * Execution of the current strand is suspended until data is available or
  * the end of the data stream is reached.
  *
  * Read operations must be exclusive. If concurrent reads are attempted a
  * StreamLockedException is thrown.
  *
  * @param integer $length The maximum number of bytes to read.
  *
  * @return string                The data read from the stream.
  * @throws StreamClosedException if the stream is already closed.
  * @throws StreamLockedException if concurrent reads are unsupported.
  * @throws StreamReadException   if an error occurs while reading from the stream.
  */
 public function read($length)
 {
     if ($this->strand) {
         throw new StreamLockedException();
     } elseif ($this->isClosed()) {
         throw new StreamClosedException();
     }
     if (!$this->buffer) {
         (yield Recoil::suspend(function ($strand) {
             $this->strand = $strand;
             $this->stream->resume();
         }));
         $this->strand = null;
     }
     if (strlen($this->buffer) > $length) {
         $buffer = substr($this->buffer, 0, $length);
         $this->buffer = substr($this->buffer, $length);
     } else {
         $buffer = $this->buffer;
         $this->buffer = '';
     }
     (yield Recoil::return_($buffer));
     // @codeCoverageIgnoreStart
 }