4 * Class for implementing a serial queue channel in memory.
6 * Portable Windows Library
8 * Copyright (c) 2001 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.2 2001/09/10 02:51:23 robertj
28 * Major change to fix problem with error codes being corrupted in a
29 * PChannel when have simultaneous reads and writes in threads.
31 * Revision 1.1 2001/07/10 03:07:07 robertj
32 * Added queue channel and delay channel classes to ptclib.
37 #pragma implementation "qchannel.h"
41 #include <ptclib/qchannel.h>
47 /////////////////////////////////////////////////////////
49 PQueueChannel::PQueueChannel(PINDEX size
)
52 queueBuffer
= new BYTE
[size
];
60 queueLength
= enqueuePos
= dequeuePos
= 0;
64 PQueueChannel::~PQueueChannel()
70 BOOL
PQueueChannel::Open(PINDEX size
)
77 queueBuffer
= new BYTE
[size
];
79 queueLength
= enqueuePos
= dequeuePos
= 0;
91 BOOL
PQueueChannel::Close()
107 BOOL
PQueueChannel::Read(void * buf
, PINDEX count
)
114 BYTE
* buffer
= (BYTE
*)buf
;
120 /* If queue is empty then we should block for the time specifed in the
123 while (queueLength
== 0) {
126 PTRACE_IF(6, readTimeout
> 0, "QChan\tBlocking on empty queue");
127 if (!unempty
.Wait(readTimeout
)) {
128 PTRACE(6, "QChan\tRead timeout on empty queue");
129 if (lastReadCount
== 0)
130 return SetErrorValues(Timeout
, EAGAIN
, LastReadError
);
135 return SetErrorValues(Interrupted
, EINTR
, LastReadError
);
140 // To make things simpler, limit to amount to copy out of queue to till
141 // the end of the linear part of memory. Another loop around will get
142 // rest of data to dequeue
143 PINDEX copyLen
= queueSize
- dequeuePos
;
145 // But do not copy more than has actually been queued
146 if (copyLen
> queueLength
)
147 copyLen
= queueLength
;
149 // Or more than has been requested
153 // Copy data out and increment pointer, decrement bytes yet to dequeue
154 memcpy(buffer
, queueBuffer
+dequeuePos
, copyLen
);
155 lastReadCount
+= copyLen
;
159 // Move the queue pointer along, wrapping to beginning
160 dequeuePos
+= copyLen
;
161 if (dequeuePos
>= queueSize
)
164 // If buffer was full, signal possibly blocked write of data to queue
165 // that it can write to queue now.
166 if (queueLength
== queueSize
) {
167 PTRACE(6, "QChan\tSignalling queue no longer full");
171 // Now decrement queue length by the amount we copied
172 queueLength
-= copyLen
;
182 BOOL
PQueueChannel::Write(const void * buf
, PINDEX count
)
189 const BYTE
* buffer
= (BYTE
*)buf
;
195 /* If queue is full then we should block for the time specifed in the
198 while (queueLength
== queueSize
) {
201 PTRACE_IF(6, writeTimeout
> 0, "QChan\tBlocking on full queue");
202 if (!unfull
.Wait(writeTimeout
)) {
203 PTRACE(6, "QChan\tWrite timeout on full queue");
204 return SetErrorValues(Timeout
, EAGAIN
, LastWriteError
);
208 return SetErrorValues(Interrupted
, EINTR
, LastWriteError
);
213 // Calculate number of bytes to copy
214 PINDEX copyLen
= count
;
216 // First don't copy more than are availble in queue
217 PINDEX bytesLeftInQueue
= queueSize
- queueLength
;
218 if (copyLen
> bytesLeftInQueue
)
219 copyLen
= bytesLeftInQueue
;
221 // Then to make things simpler, limit to amount left till the end of the
222 // linear part of memory. Another loop around will get rest of data to queue
223 PINDEX bytesLeftInUnwrapped
= queueSize
- enqueuePos
;
224 if (copyLen
> bytesLeftInUnwrapped
)
225 copyLen
= bytesLeftInUnwrapped
;
227 // Move the data in and increment pointer, decrement bytes yet to queue
228 memcpy(queueBuffer
+ enqueuePos
, buffer
, copyLen
);
229 lastWriteCount
+= copyLen
;
233 // Move the queue pointer along, wrapping to beginning
234 enqueuePos
+= copyLen
;
235 if (enqueuePos
>= queueSize
)
238 // If buffer was empty, signal possibly blocked reader of data from queue
239 // that it can read from queue now.
240 if (queueLength
== 0) {
241 PTRACE(6, "QChan\tSignalling queue no longer empty");
245 // Now increment queue length by the amount we copied
246 queueLength
+= copyLen
;
255 // End of File ///////////////////////////////////////////////////////////////