QUEUE(3C++)

NAME
queue - qheads and qtails for the C++ task library

SYNOPSIS
#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);
};

DESCRIPTION
Classes 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(3C++) 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:

    qh  a qhead object

    qt  a qtail object

    t   a task object

    qhp a pointer to a qhead

    qtp a pointer to a qtail

    op  a pointer to an object

    tp  a pointer to a task

    i, j
        ints

    eo  an objtype enumeration

    eq  a qmodetype enumeration

  Class qhead

Class qhead has one form of constructor:

qhead qh( eq, j )
    Constructs a 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):

qhp = qh.cut()
    Splits qh in two. 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.

op = qh.get()
    Returns a pointer to the 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.

eo = qh.o_type()
    Returns the class type of the object (object::QHEAD). o_type() is a virtual function.

i = qh.pending()
    Returns TRUE if the queue attached to qh is empty, and FALSE otherwise. pending() is a virtual function.

qh.print( i )
    Prints the contents of qh on stdout. It calls the 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.

i = qh.putback( op )
    Puts the 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.

i = qh.rdcount()
    Returns the current number of objects in the queue attached to qh.

i = qh.rdmax()
    Returns the maximum size of the queue attached to qh.

eq = qh.rdmode()
    Returns the current mode of qh, WMODE, EMODE, or ZMODE.

qh.setmode( eq )
    Sets the mode of qh to eq, which can be WMODE, EMODE, or ZMODE.

qh.setmax( i )
    Sets the maximum size of the queue attached to qh to i It is legal to decrease the maximum below the current number of 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.

qh.splice( qtp )
    Reverses the action of a previous 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(3C++) manual page.)

qtp = qh.tail()
    Creates a qtail object for the queue attached to qh (if none exists) and returns a pointer, qtp, to the new qtail object.

  Class qtail

Class qtail has one form of constructor:

qtail qt( eq, j )
    Constructs a 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):

qtp = qt.cut()
    Splits the queue to which it is applied in two. 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.

qhp = qt.head()
    Creates a qhead object for the queue attached to qt (if none exists) and returns a pointer to the new qhead object.

eo = qt.o_type()
    Returns the class type of the object (object::QTAIL). o_type() is a virtual function.

i = qt.pending()
    Returns TRUE if the queue attached to qt is full, and FALSE otherwise. pending() is a virtual function.

qt.print( i )
    Prints the contents of qt on stdout. It calls the 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.

i = qt.put( op )
    Adds the 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.

i = qt.rdspace()
    Returns the number of objects that can be inserted into the queue attached to qt before it becomes full.

i = qt.rdmax()
    Returns the maximum size of the queue attached to qt.

eq = qt.rdmode()
    Returns the current mode of qt, WMODE, EMODE, or ZMODE.

qt.splice( qhp )
    Reverses the action of a previous 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(3C++) manual page.)

qt.setmode( eq )
    Sets the mode of qt to eq, which can be WMODE, EMODE, or ZMODE.

qt.setmax( i )
    Sets the maximum size of the queue attached to qt to i. It is legal to decrease the maximum below the current number of 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.

DIAGNOSTICS
See task(3C++).

SEE ALSO
TASK.INTRO(3C++), task(3C++), interrupt(3C++), tasksim(3C++)
Stroustrup, B. and Shopiro, J. E., "A Set of C++ Classes for Co-routine Style Programming," in AT&T C++ Language System Release 2.0 Library Manual.