QUEUE(3C++)

NAME
queue - list management for the task library

SYNOPSIS

#include <task.h>

enum qmodetype { EMODE, WMODE, ZMODE };

class qhead: public object {
public:
	// exported constructor
	qhead(qmodetype mode=WMODE, int size=10000);

	// exported virtual functions
	virtual objtype	o_type();
	virtual int	pending();
	virtual void	print(int, int=0);

	// exported misc functions
	qhead*	cut();
	object*	get();
	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:
	// exported constructor
	qtail(qmodetype mode=WMODE, int size=10000);

	// exported virtual functions
	virtual objtype	o_type();
	virtual int	pending();
	virtual void	print(int, int = 0);

	// exported misc functions
	qtail*	cut();
	qhead*	head();
	int	put(object*);
	int	rdmax();
	qmodetype	rdmode();
	int	rdspace();
	void	setmode(qmodetype);
	void	setmax(int);
	void	splice(qhead*);
};

DESCRIPTION

The task system provides a general queue mechanism, where a queue is a first-in first-out list of objects derived from class object (see task(3C++)). No direct access is provided to a queue itself, but access is instead via the member functions of the cooperating classes qhead and qtail. Class qhead provides access to the head of the queue, primarily for removing the item at the head of the list. Class qtail provides access to the tail of the queue, primarily for adding a new item to the end of the queue.

To create a queue, first create a qhead object, call member function qhead::tail() to get access to the associated qtail. Example:
	qhead qh;		// create a queue
	qtail *qtp = qh.tail();	// retrieve the qtail
Alternatively, the qtail object could be created first, using member function qtail::head() to get access to the associated qhead. Here is an example using only heap objects:
	qtail *qtp = new qtail;	// create a queue
	qhead *qhp = qtp->head();	// retrieve the qhead

The constructors for these classes have two optional arguments, the queue mode, and the queue maximum size. The queue mode does not affect the normal operation of the queue, but only specifies what happens when an operation is attempted on a pending queue. This is further described below. The queue size is the maximum number of items allowed to be on the queue. This is useful for modeling real-world queues which have a maximum size. The size defaults to 10,000 items, but may be reset at any time via the member function setmax(). No space is preallocated for the items on a queue.

Once a queue has been created, you may append objects to it with member function qtail::put(), and retrieve the object at the head of the queue with member function qhead::get().

Like all classes derived from class object, queues have a definition of whether they are ready or pending, and the definitions are different for the head and tail of the queue. A qtail is pending when it is full; that is, when it already has its maximum number of objects. A qhead is pending when it is empty.

Each of qhead and qtail have a mode, set by the mode parameter of the constructor. The mode may be modified at any time by member function setmode(); the mode need not be the same for the head and tail of the same queue. The mode must be one of these:

WMODE
    wait mode: Adding to a full qtail or removing from an empty qhead suspends the requesting task. This mode is set if neither of the other modes is specied.

ZMODE
    zero mode: Adding to a full qtail or removing from an empty qhead returns a zero result.

EMODE
    error mode: Adding to a full qtail or removing from an empty qhead calls task_error().

Queues may be cut and spliced, allowing the insertion of filters or other tasks into queue processing. This is explained in more detail under the cut() and splice() member functions.

  Class qhead

qhead qh(m, s);
    Constructs a qhead object and its associated queue. The queue has mode m and maximum size s. The consequences of the mode and size parameters are discussed above. Member function tail() returns a pointer to the qtail object associated with the queue.

objtype ot = qh.o_type();
    This virtual function returns the kind of the object. For a qhead, the object kind is QHEAD.

int ispending = qh.pending();
    This virtual function returns non-zero (true) if the associated queue is empty, and zero (false) otherwise.

qh.print(how);
    Prints data about the associated queue on stdout (not cout). If the first int parameter, how, has the VERBOSE bit set, prints information about all the objects on the queue. The second argument is for internal use and defaults to zero.

qhead *qhp = qh.cut();
    Creates a new qhead attached to the original queue, and returns a pointer to it. Modifies the original qhead (qh) to point to a new empty queue. Use qh.tail() to retrieve the qtail associated with this new queue. qhp will point to the original qhead, and the original qtail will still be associated with the original queue. In other words, we have the following situation:
    qhp->get()
    Retrieves the first item on the original queue.
    qhp->tail()->put(op)
    Appends an object to the original queue.
    qh.get()
    Returns the first item on the new queue, once something is put there.
    qh.tail()->put(op)
    Appends an object to the new queue.
    This technique may be used to insert a filter into an existing queue without requiring any change to code using the original head and tail of that queue. The filter will use qhp->get() to retrieve objects that were placed on the queue by putting to the original qtail. The filter will use the equivalent of qhp->tail()->put(op) to put objects on the new queue which will be retrieved by code referencing the original qhead. Existing code putting and getting from the original queue will result in those object passing through the filter. The queue may be restored by using qhead::splice(). There are cut and splice functions associated with qtail, but you must use a pair of functions from the same object, either a qhead or a qtail.

object *op = qh.get();
    If the queue associated with qh is not empty, removes the object at the head of the queue and returns a pointer to it. If the queue is empty, the behavior depends on the mode of qh. If the mode is WMODE, the task calling get() is suspended until a object is put onto the queue. If the mode is ZMODE, returns a null pointer immediately. If the mode is EMODE, causes a run time error, and object::task_error() is called.

int ok = qh.putback(op);
    If the queue associated with qt is not full, puts the object pointed to by op at the head of the queue and returns the value 1 (true). A queue may be used like a stack by using only the qhead and the functions putback() and get(). If the queue is full, the behavior depends on the mode of qh. If the mode is WMODE, the task calling putback() is suspended until the queue becomes no longer full. If the mode is ZMODE, returns a zero value immediately. If the mode is EMODE, causes a run time error, and object::task_error() is called.

int i = qh.rdcount();
    Returns the number of objects currently in the associated queue.

int i = qh.rdmax();
    Returns the (current) maximum number of objects allowable in the associated queue.

qmodetype qm = qh.rdmode();
    Returns the current mode of qh: WMODE, EMODE, or ZMODE.

qh.setmode(qm);
    Sets the mode of qh to qm, which may be one of WMODE, EMODE, or ZMODE.

qh.setmax(max);
    Sets the maximum number of items allowed on the associated queue to max. It is legal to set the maximum below the current number of objects on the queue. In this case, the queue is considered full until enough objects have been removed to bring the count below the maximum.

qhp->splice(qtp);
    Reverses the previous qhead::cut() operation, where qhp was the pointer returned by the cut(), and qtp points to the qtail object associated with qhp. Recall that these head and tail pointers were associated with different queues. The splice() operation merges the two queues, and deletes the qhead and qtail objects pointed to by qhp and qtp. In the merged queue, any objects on the qtp queue are placed before any objects on the qhp queue. This restored queue again becomes associated with the original qhead and qtail objects that were cut(). If merging the queues causes a full queue to become not full, or an empty queue to become not empty, any tasks waiting for that condition will be alerted (made runnable). See task(3C++).

qtail *qtp = qh.tail();
    Returns a pointer to the qtail object associated with the queue, creating the qtail if it does not already exist.

  Class qtail

qtail qt(m, s);
    Constructs a qtail object and its associated queue. The queue has mode m and maximum size s. The consequences of the mode and size parameters are discussed above. Member function head() returns a pointer to the qhead object associated with the queue.

objtype ot = qt.o_type();
    This virtual function returns the kind of the object. For a qtail, the object kind is QTAIL.

int ispending = qt.pending();
    This virtual function returns non-zero (true) if the associated queue is full, and zero (false) otherwise.

qt.print(how);
    Prints data about the associated queue on stdout (not cout). If the first int parameter, how, has the VERBOSE bit set, prints information about all the objects on the queue. The second argument is for internal use and defaults to zero.

qtail *qtp = qt.cut();
    Creates a new qtail attached to the original queue, and returns a pointer to it. Modifies the original qtail (qt) to point to a new empty queue. Use qt.head() to retrieve the qhead associated with this new queue. qtp will point to the original qtail, and the original qhead will still be associated with the original queue. In other words, we have the following situation:
    qt.head()->get()
    Retrieves the first item on the original queue. That is, the original qhead still retrieves items from the original queue.
    qtp->put(op)
    Appends an object to the original queue.
    qt.head()->get()
    Returns the first item on the new queue, once something is put there.
    qt.put(op)
    Appends an object to the new queue.
    This technique may be used to insert a filter into an existing queue without requiring any change to code using the original head and tail of that queue. The filter will use the equivalent of qtp->head()->get() to retrieve objects that were placed on the new queue by putting to the original qtail. The filter will use qtp->put(op) to put objects on the original queue which will be retrieved by code referencing the original qhead. Existing code putting and getting from the original queue will result in those object passing through the filter. The queue may be restored by using qtail::splice(). There are cut and splice functions associated with qhead, but you must use a pair of functions from the same object, either a qhead or a qtail.

qhead *qtp = qt.head();
    Returns a pointer to the qhead object associated with the queue, creating the qhead if it does not already exist.

int ok = qt.put(op);
    If the queue associated with qt is not full, appends the object pointed to by op to the queue and returns the value 1 (true). If the queue is full, the behavior depends on the mode of qt. If the mode is WMODE, the task calling put() is suspended until the queue becomes no longer full. If the mode is ZMODE, returns a zero value immediately. If the mode is EMODE, causes a run time error, and object::task_error() is called.

int i = qt.rdmax();
    Returns the (current) maximum number of objects allowable in the associated queue.

qmodetype qm = qt.rdmode();
    Returns the current mode of qt: WMODE, EMODE, or ZMODE.

int i = qt.rdspace();
    Returns the number of objects which may be appended to the associated queue before it becomes full.

qt.setmode(qm);
    Sets the mode of qt to qm, which may be one of WMODE, EMODE, or ZMODE.

qt.setmax(max);
    Sets the maximum number of items allowed on the associated queue to max. It is legal to set the maximum below the current number of objects on the queue. In this case, the queue is considered full until enough objects have been removed to bring the count below the maximum.

qtp->splice(qhp);
    Reverses the previous qtail::cut() operation, where qtp was the pointer returned by the cut(), and qhp points to the qhead object associated with qtp. Recall that these head and tail pointers were associated with different queues. The splice() operation merges the two queues, and deletes the qhead and qtail objects pointed to by qhp and qtp. In the merged queue, any objects on the qtp queue are placed before any objects on the qhp queue. This restored queue again becomes associated with the original qhead and qtail objects that were cut(). If merging the queues causes a full queue to become not full, or an empty queue to become not empty, any tasks waiting for that condition will be alerted (made runnable). See task(3C++).

DIAGNOSTICS

See task(3C++).

SEE ALSO
TASK.INTRO(3C++), interrupt(3C++), task(3C++), tasksim(3C++)

Task Library Tutorial