source: vendor/trolltech/current/src/kernel/qasyncio.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 10.0 KB
Line 
1/****************************************************************************
2** $Id: qasyncio.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of asynchronous I/O classes
5**
6** Created : 970617
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qasyncio.h"
39#include "qiodevice.h"
40#include <stdlib.h>
41
42#ifndef QT_NO_ASYNC_IO
43
44/*!
45 \class QAsyncIO qasyncio.h
46 \obsolete
47 \brief The QAsyncIO class encapsulates I/O asynchronicity.
48
49 The Qt classes for asynchronous input/output provide a simple
50 mechanism to allow large files or slow data sources to be processed
51 without using large amounts of memory or blocking the user interface.
52
53 This facility is used in Qt to drive animated images. See QImageConsumer.
54*/
55
56
57/*!
58 Destroys the async IO object.
59*/
60QAsyncIO::~QAsyncIO()
61{
62}
63
64/*!
65 Ensures that only one object, \a obj and function, \a member, can
66 respond to changes in readiness.
67*/
68void QAsyncIO::connect(QObject* obj, const char *member)
69{
70 signal.disconnect(0, 0);
71 signal.connect(obj, member);
72}
73
74/*!
75 Derived classes should call this when they change from being
76 unready to ready.
77*/
78void QAsyncIO::ready()
79{
80 signal.activate();
81}
82
83
84
85/*!
86 \class QDataSink qasyncio.h
87 \obsolete
88 \brief The QDataSink class is an asynchronous consumer of data.
89
90 A data sink is an object which receives data from some source in an
91 asynchronous manner. This means that at some time not determined by
92 the data sink, blocks of data are given to it from processing. The
93 data sink is able to limit the maximum size of such blocks which it
94 is currently able to process.
95
96 \sa QAsyncIO, QDataSource, QDataPump
97*/
98
99/*!
100 \fn int QDataSink::readyToReceive()
101
102 The data sink should return a value indicating how much data it is ready
103 to consume. This may be 0.
104*/
105
106/*!
107 This should be called whenever readyToReceive() might have become non-zero.
108 It is merely calls QAsyncIO::ready() if readyToReceive() is non-zero.
109*/
110void QDataSink::maybeReady()
111{
112 if (readyToReceive()) ready();
113}
114
115/*!
116 \fn void QDataSink::receive(const uchar*, int count)
117
118 This function is called to provide data for the data sink. The \a count
119 will be no more than the amount indicated by the most recent call to
120 readyToReceive(). The sink must use all the provided data.
121*/
122
123/*!
124 \fn void QDataSink::eof()
125
126 This function will be called when no more data is available for
127 processing.
128*/
129
130
131/*!
132 \class QDataSource qasyncio.h
133 \obsolete
134 \brief The QDataSource class is an asynchronous producer of data.
135
136 A data source is an object which provides data from some source in an
137 asynchronous manner. This means that at some time not determined by
138 the data source, blocks of data will be taken from it for processing.
139 The data source is able to limit the maximum size of such blocks which
140 it is currently able to provide.
141
142 \sa QAsyncIO, QDataSink, QDataPump
143*/
144
145/*!
146 \fn int QDataSource::readyToSend()
147
148 The data source should return a value indicating how much data it is ready
149 to provide. This may be 0. If the data source knows it will never be
150 able to provide any more data (until after a rewind()), it may return -1.
151*/
152
153/*!
154 This should be called whenever readyToSend() might have become non-zero.
155 It is merely calls QAsyncIO::ready() if readyToSend() is non-zero.
156*/
157void QDataSource::maybeReady()
158{
159 if (readyToSend()) ready();
160}
161
162/*!
163 \fn void QDataSource::sendTo(QDataSink*, int count)
164
165 This function is called to extract data from the source, by sending
166 it to the given data sink. The \a count will be no more than the amount
167 indicated by the most recent call to readyToSend(). The source must
168 use all the provided data, and the sink will be prepared to accept at
169 least this much data.
170*/
171
172/*!
173 This function should return TRUE if the data source can be rewound.
174
175 The default returns FALSE.
176*/
177bool QDataSource::rewindable() const
178{
179 return FALSE;
180}
181
182/*!
183 If this function is called with \a on set to TRUE, and rewindable()
184 is TRUE, then the data source must take measures to allow the rewind()
185 function to subsequently operate as described. If rewindable() is FALSE,
186 the function should call QDataSource::enableRewind(), which aborts with
187 a qFatal() error.
188
189 For example, a network connection may choose to use a disk cache
190 of input only if rewinding is enabled before the first buffer-full of
191 data is discarded, returning FALSE in rewindable() if that first buffer
192 is discarded.
193*/
194void QDataSource::enableRewind( bool /* on */ )
195{
196 qFatal( "Attempted to make unrewindable QDataSource rewindable" );
197}
198
199/*!
200 This function rewinds the data source. This may only be called if
201 enableRewind(TRUE) has been previously called.
202*/
203void QDataSource::rewind()
204{
205 qFatal("Attempted to rewind unrewindable QDataSource");
206}
207
208/*!
209 \class QIODeviceSource qasyncio.h
210 \obsolete
211 \brief The QIODeviceSource class is a QDataSource that draws data from a QIODevice.
212
213 This class encapsulates retrieving data from a QIODevice (such as a QFile).
214*/
215
216/*!
217 Constructs a QIODeviceSource from the QIODevice \a device. The QIODevice
218 \e must be dynamically allocated, becomes owned by the QIODeviceSource,
219 and will be deleted when the QIODeviceSource is destroyed. \a buffer_size
220 determines the size of buffering to use between asynchronous operations.
221 The higher the \a buffer_size, the more efficient, but the less interleaved
222 the operation will be with other processing.
223*/
224QIODeviceSource::QIODeviceSource(QIODevice* device, int buffer_size) :
225 buf_size(buffer_size),
226 buffer(new uchar[buf_size]),
227 iod(device),
228 rew(FALSE)
229{
230}
231
232/*!
233 Destroys the QIODeviceSource, deleting the QIODevice from which it was
234 constructed.
235*/
236QIODeviceSource::~QIODeviceSource()
237{
238 delete iod;
239 delete [] buffer;
240}
241
242/*!
243 Ready until end-of-file.
244*/
245int QIODeviceSource::readyToSend()
246{
247 if ( iod->status() != IO_Ok || !(iod->state() & IO_Open) )
248 return -1;
249
250 int n = QMIN((uint)buf_size, iod->size()-iod->at()); // ### not 64-bit safe
251 // ### not large file safe
252 return n ? n : -1;
253}
254
255/*!
256 Reads a block of data and sends up to \a n bytes to the \a sink.
257*/
258void QIODeviceSource::sendTo(QDataSink* sink, int n)
259{
260 iod->readBlock((char*)buffer, n);
261 sink->receive(buffer, n);
262}
263
264/*!
265 All QIODeviceSource's are rewindable.
266*/
267bool QIODeviceSource::rewindable() const
268{
269 return TRUE;
270}
271
272/*!
273 If \a on is set to TRUE then rewinding is enabled.
274 No special action is taken. If \a on is set to
275 FALSE then rewinding is disabled.
276*/
277void QIODeviceSource::enableRewind(bool on)
278{
279 rew = on;
280}
281
282/*!
283 Calls reset() on the QIODevice.
284*/
285void QIODeviceSource::rewind()
286{
287 if (!rew) {
288 QDataSource::rewind();
289 } else {
290 iod->reset();
291 ready();
292 }
293}
294
295
296/*!
297 \class QDataPump qasyncio.h
298 \obsolete
299 \brief The QDataPump class moves data from a QDataSource to a QDataSink during event processing.
300
301 For a QDataSource to provide data to a QDataSink, a controller must exist
302 to examine the QDataSource::readyToSend() and QDataSink::readyToReceive()
303 methods and respond to the QASyncIO::activate() signal of the source and
304 sink. One very useful way to do this is interleaved with other event
305 processing. QDataPump provides this - create a pipe between a source
306 and a sink, and data will be moved during subsequent event processing.
307
308 Note that each source can only provide data to one sink and each sink
309 can only receive data from one source (although it is quite possible
310 to write a multiplexing sink that is multiple sources).
311*/
312
313/*!
314 Constructs a QDataPump to move data from a given \a data_source
315 to a given \a data_sink.
316*/
317QDataPump::QDataPump(QDataSource* data_source, QDataSink* data_sink) :
318 source(data_source), sink(data_sink)
319{
320 source->connect(this, SLOT(kickStart()));
321 sink->connect(this, SLOT(kickStart()));
322 connect(&timer, SIGNAL(timeout()), this, SLOT(tryToPump()));
323 timer.start(0, TRUE);
324}
325
326void QDataPump::kickStart()
327{
328 if (!timer.isActive()) {
329 interval = 0;
330 timer.start(0, TRUE);
331 }
332}
333
334void QDataPump::tryToPump()
335{
336 int supply, demand;
337
338 supply = source->readyToSend();
339 demand = sink->readyToReceive();
340 if (demand <= 0) {
341 return;
342 }
343 interval = 0;
344 if (supply < 0) {
345 // All done (until source signals change in readiness)
346 sink->eof();
347 return;
348 }
349 if (!supply)
350 return;
351 source->sendTo(sink, QMIN(supply, demand));
352
353 timer.start(0, TRUE);
354}
355
356#endif // QT_NO_ASYNC_IO
357
Note: See TracBrowser for help on using the repository browser.