|
|
#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 objects 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,
objects are added to it with
qtail::put()
and objects 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
ints
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.
objects that are already on the queue and objects 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()).
objects 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 objects through the queue.
The filter will intercept objects that are qtail::put()
on the original qtail when it does a qhead::get()
on the new qhead.
Then the filter can qtail::put() objects 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 tasks 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()objects in the queue attached to qh.
= qh.rdmax() = qh.rdmode().setmode(eq).setmax(i)objects on the queue.
Doing so means that no more objects 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
tasks 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.
objects 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.
objects that are qtail::put() to qt
must be retrieved via the new qhead.
objects 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 objects through the queue.
The filter will intercept objects that are
qtail::put()
on the original qtail
when it does a qhead::get()
on the new qhead.
Then the filter can
qtail::put()
objects 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()objects 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 tasks 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)objects on the queue.
Doing so means that no more objects 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.