|
|
#include <task.h>enum qmodetype { EMODE, WMODE, ZMODE };
class qhead : public object { public: qhead(qmodetype =WMODE, int =10000); ~qhead(); qhead* cut(); object* get(); objtype o_type(); int pending(); void print(int, int =0); int putback(object*); int rdcount(); int rdmax(); qmodetype rdmode(); void setmode(qmodetype); void setmax(int); void splice(qtail*); qtail* tail(); };
class qtail : public object { public: qtail(qmodetype =WMODE, int =10000); ~qtail(); qtail* cut(); qhead* head(); objtype o_type(); int pending(); void print(int, int =0); int put(object*); int rdspace(); int rdmax(); qmodetype rdmode(); void splice(qhead*); void setmode(qmodetype); void setmax(int); };
qhead
and qtail
enable a wide range of message-passing and data-buffering schemes
to be implemented simply with the C++ task system.
Both classes are derived from the base class object
,
which is described on the
task(C++)
manual page.
In general, class qhead
provides facilities
for taking objects off a queue,
and class qtail
provides facilities
for putting objects on a queue.
The objects transmitted through a queue must be of class object
or of some class derived from it.
A queue is a data structure with an
associated list of object
s in first-in, first-out order.
Each queue also has associated qhead
and qtail
objects attached (one of each).
No public functions are provided to operate on queues directly.
Rather all access to a queue is through either the attached qhead
or the attached qtail
.
To create a queue, the programmer must declare a qhead
object
and then use that object to call qhead::tail()
or must declare a qtail
object and then use that object to call
qtail::head()
.
For example:
qhead qh; qtail* qtp = qh.tail();Once the queue is established,
object
s are added to it with
qtail::put()
and object
s are removed from it with
qhead::get()
.
Objects derived from class object
have definitions of when they are
ready and pending (not ready).
qhead
objects are ready
when the queue is not empty
and pending when the queue is empty.
qtail
objects are ready
when the queue is not full,
and pending when the queue is full.
Queues have three attributes: mode, maximum size, and count.
The size and count attributes apply to the queue itself,
while the mode attribute applies independently to the qhead
and qtail
of a queue.
These attributes are described below.
Both classes qhead
and qtail
have a mode (set by the constructor)
that controls what happens when an object of that class
is pending.
The default is WMODE (wait mode).
With WMODE, a task
that executes
qhead::get()
on an empty queue will be suspended
until that queue becomes non-empty.
Similarly, with WMODE a task
that executes
qtail::put()
on a full queue will be suspended
until that queue has room for the object
to be added to the queue.
In EMODE (error mode), calling
qhead::get()
for an empty queue or calling
qtail::put()
for a full queue
will cause a run time error.
In ZMODE (zero mode), if
qhead::get()
is executed on an empty queue
it will return the NULL pointer instead of a pointer to an object.
In ZMODE, if
qtail::put()
is executed on a full queue,
it will return 0 instead of 1.
The modes of a queue's head and tail need not be the same.
Classes qhead
and qtail
both provide
a function, setmode()
, which will reset the mode.
Queues also have a maximum size,
which is set to 10000 by default.
That is, the queue can hold up to 10000 pointers to objects.
It does not, however, preallocate space.
The size of a queue can be reset with either
qhead::setmax()
or qtail::setmax()
.
The count is the number of objects on a queue.
Both the qhead
and qtail
constructors
optionally take mode and size arguments.
The public member functions supplied in the task system classes
qhead
and qtail
are listed and described in the next two sections.
The following symbols are used:
qhead
object
qtail
object
task
object
qhead
qtail
object
task
int
s
objtype
enumeration
qmodetype
enumeration
qhead
has one form of constructor:
qhead
qh(
eq,
j)
qhead
object, qh.
Both arguments are optional and have default values.
eq represents the mode (see above),
which can be WMODE, EMODE, or ZMODE.
WMODE is the default.
j represents the maximum length of the queue attached to qh;
the default is 10000.
The public member functions of class qhead
are (in alphabetical order):
=
qh.cut()
qhead::cut()
returns a pointer to a new qhead
,
which is attached to the original queue.
object
s that are already on the queue and object
s that are
qtail::put()
on the original queue must be retrieved via qhp.
qhead::cut()
modifies qh to point to a new empty queue.
A new qtail
must be established for qh (with
qh.tail()
).
object
s that are qtail::put()
to the new qtail
can be retrieved via a qh.get()
.
Thus, qhead::cut()
can be used to insert a filter into an existing
queue, without changing the appearance of the queue to anyone using it,
and without halting the flow of object
s through the queue.
The filter will intercept object
s that are qtail::put()
on the original qtail
when it does a qhead::get()
on the new qhead
.
Then the filter can qtail::put()
object
s on the new
qtail
, where execution of qhead::get()
on the original qhead
will retrieve them.
In other words, the filter task
uses the newly established
qhead
and qtail
, while other tasks
continue to
put()
and get()
from the original qtail
and qhead
.
qhead::splice()
can be used to restore the queue to its
original configuration.
=
qh.get()
object
at the head of the queue,
if the queue is not empty.
If the queue is empty, qhead::get()
's
behavior depends on the mode of qh.
In WMODE, a task
that executes qhead::get()
on an
empty queue will be suspended until that queue becomes non-empty,
when the operation can complete successfully.
In EMODE, it will cause a run time error.
In ZMODE, it will return the NULL pointer instead of a
pointer to an object
.
=
qh.o_type()
object::QHEAD
).
o_type()
is a virtual function.
=
qh.pending()
pending()
is a virtual function.
.print(
i)
print()
function for the object
base class.
i specifies the amount of information to be printed.
It can be 0, for the minimum amount of information,
or VERBOSE, for more information.
A second integer argument is for internal use and defaults to 0.
print()
is a virtual function.
=
qh.putback(
op)
object
denoted by op back on the head of the
queue attached to qh, and returns 1 on success.
This allows a qhead
to operate as a stack.
A task
calling qhead::putback()
competes for queue space
with task
s using qtail::put()
.
Calling qhead::putback()
for a full queue causes a run time
error in both EMODE and WMODE, and returns NULL
in ZMODE.
=
qh.rdcount()
object
s in the queue attached to qh.
=
qh.rdmax()
=
qh.rdmode()
.setmode(
eq)
.setmax(
i)
objects
on the queue.
Doing so means that no more object
s can be put on the queue
until the queue has been drained below the new limit.
.splice(
qtp )
qhead::cut()
.
qhead::splice()
merges the queue attached to qh
with the queue attached to qtp.
The list of objects
on the latter queue precede those on the
former queue in the merged list.
qhead::splice()
deletes qh and qtp.
qh is meant to be a qhead
that was previously cut()
,
and qtp is meant to be the pointer returned by that cut()
.
If in merging the queues qhead::splice()
causes an empty queue to
become non-empty or a full queue to become non-full, it will alert all
task
s waiting for that state change, and add them to the scheduler's
run chain.
(See object::alert()
on the
task(C++)
manual page.)
=
qh.tail()
qtail
object for the queue attached to qh (if
none exists) and returns a pointer, qtp, to the new qtail
object.
qtail
has one form of constructor:
qtail
qt(
eq,
j)
qtail
object, qt.
Both arguments are optional and have default values.
eq represents the mode (see above),
which can be WMODE, EMODE, or ZMODE.
WMODE is the default.
j represents the maximum length of the queue attached to qt;
the default is 10000.
The public member functions of class qtail
are (in alphabetical order):
=
qt.cut()
qtail::cut()
returns a pointer to a new qtail
,
which is attached to the original queue.
object
s already on the original queue can still be retrieved
with a qhead::get()
to the original qhead
.
(This is the primary functional difference between
qhead::cut()
and qtail::cut()
.)
qtail::cut()
modifies qt to point to a new empty queue.
A new qhead
must be established for qt.
object
s that are qtail::put()
to qt
must be retrieved via the new qhead
.
object
s that are qtail::put()
to qtp
will be retrieved via the original qhead
.
Thus, qtail::cut()
can be used to insert a filter into an existing queue,
without changing the appearance of the queue to anyone using it,
and without halting the flow of object
s through the queue.
The filter will intercept object
s that are
qtail::put()
on the original qtail
when it does a qhead::get()
on the new qhead
.
Then the filter can
qtail::put()
object
s on the new qtail
,
where execution of
qhead::get()
on the original qhead
will retrieve them.
In other words, the filter task
uses the newly established
qhead
and qtail
, while other tasks
continue to
put()
and get()
from the original qtail
and qhead
.
qtail::splice()
can be used to restore the queue to its original configuration.
=
qt.head()
qhead
object for the queue attached to qt (if
none exists) and returns a pointer to the new qhead
object.
=
qt.o_type()
object::QTAIL
).
o_type()
is a virtual function.
=
qt.pending()
pending()
is a virtual function.
.print(
i)
print()
function for the object
base class.
i specifies the amount of information to be printed.
It can be 0, for the minimum amount of information,
or VERBOSE, for more information.
A second integer argument is for internal use and defaults to 0.
print()
is a virtual function.
=
qt.put(
op)
object
denoted by op to the tail of the queue
attached to qt, and returns 1 on success.
If the queue is full, qtail::put()
's
behavior depends on the mode of qt.
In WMODE, a task
that executes qtail::put()
on a full queue will be suspended
until that queue becomes non-full,
when the operation can complete successfully.
In EMODE, it will cause a run time error.
In ZMODE, it will return NULL.
=
qt.rdspace()
object
s that can be inserted into the queue
attached to qt before it becomes full.
=
qt.rdmax()
=
qt.rdmode()
.splice(
qhp)
qtail::cut()
.
qtail::splice()
merges the queue attached to qt
with the queue attached to qhp.
The list of objects
on the former queue precede
those on the latter queue in the merged list.
qtail::splice()
deletes qt and qhp.
qt is meant to be a qtail
that was previously cut()
,
and qhp is meant to be the pointer returned by that
cut()
.
If in merging the queues
qtail::splice()
causes an empty queue to become non-empty
or a full queue to become non-full,
it will alert all task
s waiting for that state change,
and add them to the scheduler's
run chain.
(See object::alert()
on the
task(C++)
manual page.)
.setmode(
eq)
.setmax(
i)
object
s on the queue.
Doing so means that no more object
s can be put on the queue
until the queue has been drained below the new limit.
``A set of C++ classes for co-routine style programming,'' by Stroustrup, B. and Shopiro, J. E., in the C++ Library Manual.