Logo Search packages:      
Sourcecode: pwlib version File versions  Download package

BOOL PQueueChannel::Read ( void *  buf,
PINDEX  len 
) [virtual]

Low level read from the file channel. The read timeout is ignored for file I/O. The GetLastReadCount() function returns the actual number of bytes read.

The GetErrorCode() function should be consulted after Read() returns FALSE to determine what caused the failure.

Returns:
TRUE indicates that at least one character was read from the channel. FALSE means no bytes were read due to timeout or some other I/O error.
Parameters:
bufPointer to a block of memory to receive the read bytes.
lenMaximum number of bytes to read into the buffer.

Reimplemented from PChannel.

Definition at line 125 of file qchannel.cxx.

References PChannel::Interrupted, PChannel::IsOpen(), PChannel::lastReadCount, PChannel::LastReadError, PChannel::readTimeout, PChannel::SetErrorValues(), PSemaphore::Signal(), PSync::Signal(), PChannel::Timeout, PSemaphore::Wait(), and PSync::Wait().

Referenced by Test5Thread::Main().

{
  mutex.Wait();

  lastReadCount = 0;

  if (!IsOpen()) {
    mutex.Signal();
    return FALSE;
  }

  BYTE * buffer = (BYTE *)buf;

  /* If queue is empty then we should block for the time specifed in the
      read timeout.
    */
  while (queueLength == 0) {

    // unlock the data
    mutex.Signal();

    // block until data has arrived
    PTRACE_IF(6, readTimeout > 0, "QChan\tBlocking on empty queue");
    if (!unempty.Wait(readTimeout)) {
      PTRACE(6, "QChan\tRead timeout on empty queue");
      return SetErrorValues(Timeout, EAGAIN, LastReadError);
    }

    // relock the data
    mutex.Wait();

    // check if the channel is still open
    if (!IsOpen()) {
      mutex.Signal();
      return SetErrorValues(Interrupted, EINTR, LastReadError);
    }
  }

  // should always have data now
  PAssert(queueLength > 0, "read queue signalled without data");

  // To make things simpler, limit to amount to copy out of queue to till
  // the end of the linear part of memory. Another loop around will get
  // rest of data to dequeue
  PINDEX copyLen = queueSize - dequeuePos;

  // But do not copy more than has actually been queued
  if (copyLen > queueLength)
    copyLen = queueLength;

  // Or more than has been requested
  if (copyLen > count)
    copyLen = count;

  PAssert(copyLen > 0, "zero copy length");

  // Copy data out and increment pointer, decrement bytes yet to dequeue
  memcpy(buffer, queueBuffer+dequeuePos, copyLen);
  lastReadCount += copyLen;
  buffer += copyLen;
  count -= copyLen;

  // Move the queue pointer along, wrapping to beginning
  dequeuePos += copyLen;
  if (dequeuePos >= queueSize)
    dequeuePos = 0;

  // If buffer was full, signal possibly blocked write of data to queue
  // that it can write to queue now.
  if (queueLength == queueSize) {
    PTRACE(6, "QChan\tSignalling queue no longer full");
    unfull.Signal();
  }

  // Now decrement queue length by the amount we copied
  queueLength -= copyLen;

  // unlock the buffer
  mutex.Signal();

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Generated by  Doxygen 1.6.0   Back to index