United States |
Previous | Contents | Index |
Serves as the basis for coroutines.
#include <task.hxx>#include <task.h>
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(); };
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)
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
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.
task(char *name = (char *)NULL, modetype mode = DEFAULT_MODE,
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.
int stacksize = 0)
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. On OpenVMS systems, the C++ compiler automatically prevents inlining of constructors for classes derived from task ; that is, functions that (implicitly) call task::task (char * = 0, modetype = DEFAULTMODE, int = SIZE) .~task()
Deletes an object of the task class. It deletes the task name if the constructor created the name.
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: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() .
- Executing a return statement
- Throwing an exception
- Not catching an exception thrown by a subroutine
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).
long t = sched::get_clock; delay(10000); |
Delays a task so that it resumes executing at t+10,000.
A timer delays for a specified amount of simulated time.
#include <task.hxx>#include <task.h>
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(); };
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.
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
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 .
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 .
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
Objects of the urand class generate uniformly distributed random integers within a given range from a low to a high value.
#include <task.hxx>#include <task.h>
class urand: public randint { public: int low; int high; urand(int arg_low, int arg_high); int draw(); };
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.
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.
int draw()
Returns the next random integer generated by the object.
randint class
Previous | Next | Contents | Index |
|