|
Compaq C++
Compaq C++ Class Library Reference Manual
task class
Serves as the basis for coroutines.
Header
#include <task.hxx>
Alternative Header
#include <task.h>
Declaration
class task: public sched
{
public:
enum modetype
{
DEDICATED = 1,
SHARED = 2
};
protected:
task(char *name = (char *)NULL,
modetype mode = DEFAULT_MODE, int stacksize = 0);
public:
task *t_next;
char *t_name;
~task();
void cancel(int);
void delay(long);
long preempt();
void resultis(int);
void setwho(object *);
void sleep(object *object_waiting_for = (object *)NULL);
void wait(object *);
int waitlist(object * ...);
int waitvec(object **);
object *who_alerted_me();
virtual void print(int verbosity, int internal_use = 0);
virtual objtype o_type();
static task *get_task_chain();
};
|
Description
This class is used only as a base class; all coroutine classes are
derived from it. All work for an object of a given coroutine type
occurs within the constructor for that type. The coroutine class must
be exactly one level of derivation from the task class. When the object
is created, the constructor takes control and runs until halted by one
of the following functions:
wait()
,
waitlist()
,
waitvec()
,
sleep()
, or
resultis()
.
When a
task
executes a blocking function on an
object
that is ready, the operation succeeds immediately and the
task
continues running; if the object is pending, the
task
waits. Control then returns to the scheduler, which selects the next
task
from the ready list or run chain. When a pending object becomes ready,
the system puts any
task
waiting for that object back on the run chain.
A
task
can be in one of the following states:
RUNNING
|
Running or ready to run
|
IDLE
|
Waiting for a pending
object
|
TERMINATED
|
Completed; not able to resume running (but you can retrieve the result)
|
Exception Handling
When a run-time error occurs, the appropriate error code from the
following table is passed to the
object::task_error()
function:
Value |
Error Description |
E_RESULT
|
Cannot call
result()
on
thistask
|
E_STACK
|
Cannot extend stack
|
E_STORE
|
Cannot allocate more memory
|
E_TASKDEL
|
Cannot delete a task that is
IDLE
or
RUNNING
|
E_TASKMODE
|
Cannot create a task with a mode other than
DEDICATED
or
SHARED
|
E_TASKNAMEOVERRUN
|
Internal error: data overrun when building default task name
|
E_TASKPRE
|
Cannot preempt a task that is
IDLE
or
TERMINATED
|
E_WAIT
|
Cannot call
wait()
on
thistask
|
Member Data
task *t_next
Points to the text task on the chain of all
task
objects; it is equal to
NULL
if there are no more tasks.
char *t_name
Points to the null-terminated task name passed to the constructor. If
no name was passed to the constructor, then the constructor creates a
unique name (and t_name points to it). If the constructor
created the name, then the destructor deletes the name.
Constructors and Destructors
task(char *name = (char *)NULL, modetype mode = DEFAULT_MODE,
int stacksize = 0)
Constructs a
task
object. All three arguments are optional and have default values. If
you supply a character pointer, name is used as the
task
object's name. The argument mode must be
DEDICATED
or
SHARED
(or omitted) but only
DEDICATED
is implemented; thus, the mode argument has no effect. The
argument stacksize specifies the minimum size of the
task
object's stack. By default, the stack size is the same as the default
for the underlying thread system.
Note
With
DEDICATED
stacks, the addresses of parameters to a constructor derived from the
task
class change. This change occurs between the time when the base class (
task
) constructor is called by the derived class constructor and when the
first statement in the derived class constructor begins executing.
Constructors for the
task
class and the classes derived from the
task
class cannot be inlined. These classes perform actions that start up a
child task (in a new thread) and then resume execution of the parent
task. To prevent these constructors from being inlined, use the
-noinline
command-line switch to specify no inlining when you compile your
program, or put the constructor in a separate source file from the
parts of the program that you want to inline.
|
~task()
Deletes an object of the
task
class. It deletes the task name if the constructor created the name.
Member Functions
void cancel(int result)
Puts a task object into the
TERMINATED
state without suspending the calling
task
(that is, without invoking the scheduler); sets the result of the
object to result.
void delay(long delay)
Suspends a task object for the time specified by delay. A
delayed task is in the
RUNNING
state. The task object resumes at the current time on the system clock,
plus the time specified by delay. Only calling
delay()
, or waiting for a timer, advances the clock.
task *get_task_chain()
Returns a pointer to the first task on the list of all task objects
linked by
next_t
pointers.
virtual objtype o_type()
Returns
object::TASK
.
long preempt()
Suspends a
RUNNING
object of the
task
class making it
IDLE
. Returns the number of time units left in the task's delay. Calling
this function for an
IDLE
or
TERMINATED
task causes a run-time error.
virtual void print(int verbosity, int internal_use = 0)
Prints a task object on
cout
. The verbosity argument specifies the information to be
printed. For more information, see the enum Print Function Arguments section under
Global Declarations for the task package. Do not supply a value for the
internal_use parameter.
void resultis(int result)
Sets the return value of a
task
object to be the value of result; it puts the
task
object in the
TERMINATED
state. To examine the result, call the
sched::result()
function. The constructor for a class derived from
task
must not return by any of the following actions:
- Executing a return statement
- Throwing an exception
- Not catching an exception thrown by a subroutine
The end of a constructor for a class derived from the
task
class and the
main
function must call the
resultis()
function. A task is pending until its stage changes to
TERMINATED
. For more information, see
sched::pending()
.
void setwho(object *alerter)
Keeps track of which object alerted the object. The alerter
argument should represent a pointer to the
object
that caused the task package to alert the
task
.
void sleep(object *object_waiting_for)
Suspends a
task
object unconditionally (that is, it puts the
task
object in the
IDLE
state). The argument object_waiting_for is optional; if it is
pointing to a pending object, the object remembers the task. When the
object is no longer pending, the task is rescheduled. If you do not
supply an argument, the event that causes the
task
object to resume remains unspecified.
void wait(object *object_waiting_for)
Suspends a
task
object (it puts the
task
object in the
IDLE
state) until that
object
is ready, if object_waiting_for points to an
object
that is pending. If object_waiting_for points to an
object
that is ready (not pending), then
task::wait
does not suspend the
task
object.
int waitlist(object *first_object_waiting_for ...)
Suspends a
task
object to wait for one of a list of objects to become ready. The
waitlist()
function takes a list of
object
pointers linked by
o_next
and terminated by a NULL argument. If any of the arguments point to a
ready
object
, then the
task
object is not suspended. When one of the objects pointed to in the
argument list is ready,
waitlist()
returns the position in the list of the object that caused the return;
position numbering starts at 0.
int waitvec(object **object_waiting_for_vector)
Differs from
waitlist()
only in that
waitvec()
takes as an argument the address of a vector holding a list of pointers
to objects and terminating NULL. When one of the objects pointed to in
the argument vector is ready,
waitvec()
returns the position in a vector of the object that caused the return;
position numbering starts at 0.
object *who_alerted_me()
Returns a pointer to the
object
whose state change, from pending to ready, caused a task to be put back
on the run chain (put in the
RUNNING
state).
Example
|
long t = sched::get_clock;
delay(10000);
|
Delays a task so that it resumes executing at t+10,000.
timer class
A timer delays for a specified amount of simulated time.
Header
#include <task.hxx>
Alternative Header
#include <task.h>
Declaration
class timer: public sched
{
public:
timer(long delay);
~timer();
void reset(long delay);
void setwho(object *alerter);
virtual void print(int verbosity, int internal_use = 0);
virtual objtype o_type();
};
|
Description
Objects of this class are timers. When a timer is created its state is
RUNNING
, and it is scheduled to change its state to
TERMINATED
after a specified number of time units. When the timer becomes
TERMINATED
, tasks waiting for it are scheduled to resume execution.
Exception Handling
When a run-time error occurs, the following error code is passed to the
object::task_error()
function:
Value |
Error Description |
E_TIMERDEL
|
Cannot delete a timer that is
IDLE
or
RUNNING
|
Constructors and Destructors
timer(long delay)
Constructs an object of the
timer
class and schedules it for delay time units after the current
clock time.
~timer()
Deletes an object of the
timer
class; the timer's state must be
TERMINATED
.
Member Functions
virtual objtype o_type()
Returns
object::TIMER
.
virtual void print(int verbosity, int internal_use = 0)
Prints a
timer
object on
cout
. The verbosity argument specifies the information to be
printed. For more information, see the enum Print Function Arguments section under
Global Declarations for the task package. Do not supply a value for the
internal_use parameter.
void reset(long delay)
Sets the state of the timer to
RUNNING
(even if it was
TERMINATED
) and reschedules it to terminate after the specified delay from the
current simulated time.
void setwho(object *alerter)
Returns
NULL
.
Example
extern "C" {
#include <stdlib.h>
}
#include <task.hxx>
#include <iostream.hxx>
class DelayTask: public task
{
public:
DelayTask(char *, long);
};
// This task just does a delay, much like a timer.
DelayTask::DelayTask(char *task_name, long delay_length):
task(task_name)
{
cout << "at beginning of DelayTask, clock is "
<< sched::get_clock() << "\n";
delay(delay_length);
cout << "at end of DelayTask, clock is "
<< sched::get_clock() << "\n";
thistask->resultis(0);
}
int main()
{
cout << "at beginning of main\n";
cout << "creating task\n";
DelayTask delay_task1("delay_task1", 100);
cout << "creating timer\n";
timer *pt1 = new timer(10);
cout << "waiting for timer\n";
thistask->wait(pt1);
cout << "clock is " << sched::get_clock() << "\n";
cout << "resetting timer\n";
pt1->reset(1000);
cout << "waiting for timer\n";
thistask->wait(pt1);
cout << "clock is " << sched::get_clock() << "\n";
cout << "at end of main\n";
thistask->resultis(0);
return EXIT_SUCCESS;
}
|
This code generates the following output:
at beginning of main
creating task
at beginning of DelayTask, clock is 0
creating timer
waiting for timer
clock is 10
resetting timer
waiting for timer
at end of DelayTask, clock is 100
clock is 1010
at end of main
|
urand class
Objects of the
urand
class generate uniformly distributed random integers within a given
range from a low to a high value.
Header
#include <task.hxx>
Alternative Header
#include <task.h>
Declaration
class urand: public randint
{
public:
int low;
int high;
urand(int arg_low, int arg_high);
int draw();
};
|
Data Members
int low
Is the lower bound of the range of generated random numbers.
int high
Is the upper bound of the range of generated random numbers.
Constructor
urand(int arg_low, int arg_high)
Constructs an object of the
urand
class. Generated random numbers are uniformly distributed from
arg_low to arg_high.
Member Function
int draw()
Returns the next random integer generated by the object.
See Also
randint
class
|
|
|