[an error occurred while processing this directive]

HP OpenVMS Systems

C++ Programming Language
Content starts here HP C++

HP C++
Class Library Reference Manual


Previous Contents Index


Chapter 10
task Package

Note

The task package is supported on VAX and Alpha platforms. It is not supported on the Linux Alpha platform or on OpenVMS I64 systems. The recommended replacement is the set of pthreads routines from the C++ standard library.

The task package provides coroutine support. A coroutine, or task, is a subroutine that can suspend execution to allow other tasks to run. Static data is shared among all tasks; automatic and register data is allocated separately for each task. Only one task can execute at a time, even on a multiprocessor system.

Programming with tasks can be particularly appropriate for simulations or other applications that can be reasonably represented as sets of concurrent activities.

This package includes the object and randint classes, the subclasses derived from these classes, and the histogram class.

Figure 10-1 shows the inheritance structure of the task package.

Figure 10-1 Inheritance Diagram for the task Package


Also note the following:

  • The sched and task classes are intended for use only as base classes.
  • The task package makes use of the threads library.
  • The task package is not thread safe. You cannot create tasks simultaneously from different threads.

Global Declarations

The typedef , enum , and extern declarations are used by one or more classes in the task package but they are not members of any particular class.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


typedef int(*PFIO)(int, object*); 
typedef void(*PFV)(); 
 
enum 
{ 
    VERBOSE = 1 << 0, 
    CHAIN = 1 << 1, 
    STACK = 1 << 2, 
}; 
    
enum qmodetype 
{ 
    EMODE,   
    WMODE,   
    ZMODE    
}; 
 
enum 
{ 
    E_OLINK = 1, 
    E_ONEXT = 2, 
    E_GETEMPTY = 3, 
    E_PUTOBJ = 4, 
    E_PUTFULL = 5, 
    E_BACKOBJ = 6, 
    E_BACKFULL = 7, 
    E_SETCLOCK = 8, 
    E_CLOCKIDLE = 9, 
    E_RESTERM = 10, 
    E_RESRUN = 11, 
    E_NEGTIME = 12, 
    E_RESOBJ = 13, 
    E_HISTO = 14, 
    E_STACK = 15, 
    E_STORE = 16, 
    E_TASKMODE = 17, 
    E_TASKDEL = 18, 
    E_TASKPRE = 19, 
    E_TIMERDEL = 20, 
    E_SCHTIME = 21, 
    E_SCHOBJ = 22, 
    E_QDEL = 23, 
    E_RESULT = 24, 
    E_WAIT = 25, 
    E_FUNCS = 26, 
    E_FRAMES = 27, 
    E_REGMASK = 28, 
    E_FUDGE_SIZE = 29, 
    E_NO_HNDLR = 30, 
    E_BADSIG = 31, 
    E_LOSTHNDLR = 32, 
    E_TASKNAMEOVERRUN = 33 
};    
 
extern int _hwm; 


Types

enum Print Function Arguments

The verbosity argument to print member functions uses the following values:

Value Explanation
0 Requests a brief report
CHAIN Requests information about tasks on the object's remember chain, and about other objects on the object's o_next chain
STACK Requests information about the run-time stack
VERBOSE Requests detailed information on the class object

To combine several requests, use the bitwise inclusive operator (|). For example:


p->print(VERBOSE|CHAIN); 

enum qmodetype

The following values are used by the qhead and qtail classes for managing queues:

Value Explanation
EMODE Generates a run-time error if full on enqueue or empty on dequeue
WMODE Suspends task execution if full on enqueue or empty on dequeue
ZMODE Returns NULL if full on enqueue or empty on dequeue

enum Exception Codes

Descriptions of the E_ codes are given in the Exception Handling sections of the appropriate classes.

PFIO

Is a pointer to a function returning int , which takes arguments of the types int and object * .

PFV

Is a pointer to a function returning void , which takes no arguments.

Other Data

extern int _hwm

Can be set to a nonzero value before creation of the first task to keep track of the maximum stack size ("high water mark"). The maximum stack size can be printed by the task::print() function.

erand class

Objects of the erand class are generators of exponentially distributed random numbers.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class erand: public randint 
{ 
public: 
    int mean; 
 
        erand(int m); 
 
    int draw(); 
}; 

Member Data

int mean

Is the mean of the generated random numbers.

Constructor

erand(int m)

Constructs an erand object with m as the mean for the generated random numbers.

Member Function

int draw()

Returns the next random integer generated by the object.

See Also

randint class

histogram class

Objects of the histogram class are generators of histograms.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class histogram 
{ 
public: 
    int   l; 
    int   r; 
    int   binsize; 
    int   nbin; 
    int   *h; 
    long  sum; 
    long  sqsum; 
 
          histogram(int n_bins = 16, int left = 0, int right = 16); 
          ~histogram(); 
 
    void  add(int sample); 
    void  print(); 
}; 

Description

Objects of this class generate histograms. Each such object has nbin bins, spanning a range from l to r .

Exception Handling

When a run-time error occurs, the following error code is passed to the object::task_error() function:
Value Error Description
E_HISTO Cannot construct a histogram with less than 1 bucket or the left not less than the right

Member Data

int binsize

Is the size of the range covered by an individual bin.

int *h

Is a pointer to a vector of nbin integers. Each element of the vector is the number of samples placed into that bin by the add() function.

int l

Is the lower (left) end of the range of samples.

int nbin

Is the total number of bins.

int r

Is the higher (right) end of the range of samples.

long sqsum

Is the sum of the squares of the integers added to a bin by the add() function.

long sum

Is the sum of the integers added to a bin by the add() function.

Constructors and Destructors

histogram(int n_bins = 16, int left = 0, int right = 16)

Constructs a histogram object. The arguments are all optional: n_bins specifies the number of bins, left specifies the initial left end of the range and right specifies the initial right end of the range. At instantiation, the member data are initialized as follows:
The count in each bin is set to 0.
The value of l is left
the value of r is right
nbin is set to n_bins
The values of sqsum and sum are 0.

~histogram()

Deletes a histogram object.

Member Functions

void add(int sample)

Adds one to the bin specified by sample. If sample is outside the range of l to r , the range expands by either decreasing l or increasing r ; however, nbin remains constant. Thus, the range covered by one bin doubles if the total histogram doubles.

void print()

Prints on cout the number of entries for each nonempty bin.

Interrupt_handler class

Interrupt handlers let tasks wait for external events (system signals), and allow the declaration of handler functions for these events.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class Interrupt_handler: public object 
{ 
public: 
                     Interrupt_handler(int); 
                     ~Interrupt_handler(); 
 
    virtual void     print(int verbosity, int internal_use = 0); 
    virtual int      pending(); 
    virtual objtype  o_type(); 
 
private: 
    virtual void interrupt(); 
}; 

Description

Interrupt handlers allow tasks to wait for signals. You can use classes derived from the Interrupt_handler class to overload the interrupt() function. When the signal is raised, the task package immediately calls the interrupt() function. The task package then schedules its own internal interrupt alerter task for execution. Control returns to the task (if any) that was running when the signal was raised. When control returns to the scheduler, the interrupt alerter runs and schedules for execution those tasks that were waiting for the interrupt handler.

If the run chain (see the sched class) is empty, the scheduler does not cause the program to exit if there are any interrupt handlers that have been created but not yet destroyed.

If an interrupt() function is not needed, you can use the Interrupt_handler class without deriving another class from it.

For more information on signals, see the C Run-Time Library Reference Manual.


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_NO_HNDLR Cannot handle a signal for which there is no handler
E_BADSIG Cannot handle a signal with an invalid signal number
E_LOSTHNDLR Cannot delete an Interrupt_handler that is not on the stack of them for the given signal

Constructors and Destructors

Interrupt_handler(int signal_to_catch)

Constructs a new Interrupt_handler object that waits for a specified signal.

~Interrupt_handler()

Deletes an Interrupt_handler object.

Member Functions

virtual void interrupt()

Does nothing but lets classes derived from the Interrupt_handler class overload this function to specify actions. Because it is private, you cannot call it directly.

virtual objtype o_type()

Returns object::INTHANDLER .

virtual int pending()

Returns 0 on the first call after the signal is raised; otherwise, it returns a nonzero value.

virtual void print(int verbosity, int internal_use = 0)

Prints information about the interrupt handler. 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.

System Environment

The thread system exception handling uses OpenVMS conditions and does not interact directly with signals.

Example


extern "C" { 
#include <stdlib.h> 
} 
#include <signal.h> 
#include <task.hxx> 
#include <iostream.hxx> 
 
class floating_exception: public Interrupt_handler 
{ 
    virtual void interrupt(); 
public: 
    floating_exception(): Interrupt_handler(SIGFPE) {}; 
}; 
 
void floating_exception::interrupt() 
{ 
    cout << "In floating_exception::interrupt -- 
    Floating exception caught!\n"; 
    cout.flush(); 
} 
 
int main() 
{ 
    floating_exception sigfpe_handler; 
    raise(SIGFPE); 
    return EXIT_SUCCESS; 
} 

This example prints out the following message:


In floating_exception::interrupt -- Floating exception caught! 

object class

Base class for other classes in the task package and for user-defined classes of objects to be placed in queues (see the qhead and qtail classes).

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class object 
{ 
public: 
    enum objtype 
    { 
        OBJECT,         // class object 
        TIMER,          // class timer 
        TASK,           // class task 
        QHEAD,          // class qhead 
        QTAIL,          // class qtail 
        INTHANDLER      // class Interrupt_handler 
    }; 
 
    object  *o_next; 
 
    static  PFIO error_fct; 
 
            object(); 
            ~object(); 
 
    void    alert(); 
    void    forget(task *p_task_to_forget); 
    void    remember(task *p_task); 
    int     task_error(int error_code); 
 
    virtual objtype o_type(); 
    virtual int pending(); 
    virtual void print(int verbosity, int internal_use = 0); 
 
    static  int task_error(int error_code, object *object_with_problem); 
    static  task *this_task(); 
}; 

Description

This class is a base class for many other classes within the task package. You also can use it to derive user classes to be placed in the task package's queues and so forth. All objects derived from the object class can declare the virtual function object::pending() , which the scheduler uses to determine if an object is ready or not ready. You can provide each kind of object with its own method of determining its state of readiness. Each pending object contains a list (the remember chain) of the waiting task objects.

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_OLINK Cannot delete an object with a remembered task
E_ONEXT Cannot delete an object that is on a list
E_STORE Cannot allocate more memory

Member Data

PFIO error_fct

Points to a function to be called by the task_error function. For more information, see the task_error function.

object *o_next

Points to the next object in the queue or run chain.

Constructors and Destructors

object()

Constructs an object object.

~object()

Deletes an object object.

Member Functions

void alert()

Changes the state of all task objects remembered by the object from IDLE to RUNNING , puts the task objects on the scheduler's run chain, and removes the task objects from the remembering object's remember chain. You must call the object::alert function for the object when the state of an object changes from pending to ready.

void forget(task *p_task_to_forget)

Removes, from the remembering object object's remember chain, all occurrences of the task , denoted by the p_task_to_forget argument.

virtual objtype o_type()

Returns object::OBJECT .

virtual int pending()

Always returns a nonzero value.

In classes derived from object , pending() returns the ready status of an object: 0 if an object object is ready and a nonzero value if the object object is pending. Classes derived from the object class must define pending() if waiting is instituted. By default, object::pending returns a nonzero value.

virtual void print(int verbosity, int internal_use = 0)

Prints an 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 remember(task *p_task)

Puts a task for a pending object on the remember chain and suspends the task , when that task attempts an operation on the pending object . Remembered task objects are alerted when an object of the object class becomes ready.

int task_error(int error_code)

Is obsolete. Calling p->task_error(e) is equivalent to calling object::task_error(e,p) .

static int task_error(int error_code, object *object_with_problem)

Called when a run-time error occurs. The error_code argument represents the error number and the object_with_problem argument represents a pointer to the object that called task_error() . The object::task_error() function examines the variable error_fct and calls this function if it is not NULL . If the function returns 0, task_error() returns to its caller, which may retry the operation. (An infinite loop may result if no appropriate recovery is made.) If the function returns a nonzero value, task_error() calls exit(error_code) . Otherwise, task_error() gives the error number as an argument to print_error() , which prints an error message on cout and task_error() calls exit(error_code) .

The object_with_problem argument may be NULL if no particular object can be associated with the error.

static task *this_task()

Returns a pointer to the task object currently running.

qhead class

Abstraction for the head of a list of items arranged in a first-in, first-out singly linked list.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class qhead: public object 
{ 
public: 
              qhead(qmodetype modetype = WMODE, int size = 10000); 
              ~qhead(); 
 
    qhead     *cut(); 
    object    *get(); 
    int       putback(object *new_queue_element); 
    int       rdcount(); 
    int       rdmax(); 
    qmodetype rdmode(); 
    void      setmode(qmodetype modetype); 
    void      setmax(int size); 
    void      splice(qtail *delete_tail); 
    qtail     *tail(); 
 
    int       pending(); 
    void      print(int verbosity, int internal_use = 0); 
    objtype   o_type(); 
}; 

Description

This class provides facilities for taking objects off a queue. A queue is a data structure with an associated list of objects of the object class, or a class derived from the object class in first-in, first-out order. All access to a queue is through either the attached qhead or attached qtail object. You create a queue by creating either a qhead or a qtail object. The other end of the queue is created automatically. You can then obtain a pointer to the tail with the qhead::tail function.

Objects have definitions for when they are ready and pending (not ready). The qhead objects are ready when the queue is not empty and pending when the queue is empty.


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_BACKFULL Cannot putback an object into a full queue
E_BACKOBJ Cannot putback an object into a queue if the object is on another queue
E_GETEMPTY Cannot get an object from an empty queue
E_QDEL Cannot delete a queue that has an object in the queue
E_STORE Cannot allocate more memory

Constructors and Destructors

qhead(qmodetype modetype = WMODE, int size = 10000)

Constructs a qhead object. The modetype argument determines what happens when an object of the qhead class is pending. The choices are WMODE (wait mode), EMODE (error mode), or ZMODE (0 mode); the default is WMODE (see the get() function for more information). The size argument sets the maximum length of the queue attached to a qhead object; the default is 10,000.

The maximum size of the queue does not affect the amount of memory occupied by the queue when the queue is empty.

~qhead()

Deletes a qhead object.


Member Functions

qhead *cut()

Splits a queue into two queues. One queue has a new qhead object, which the return value points to, and the original qtail object; it contains the objects from the original queue. The other queue has the original qhead object and a new qtail object; this queue is empty. You can use this function to insert a filter into an existing queue without changing the queue's appearance to functions that access the ends of the queue, and without halting the flow through the queue of objects.

object *get()

Returns a pointer to the object at the head of the queue when the queue is not empty. The object is removed from the queue. If the queue is empty, behavior depends on the mode of the qhead object. In WMODE , a task that executes qhead::get() on an empty queue suspends until that queue is not empty. In EMODE , executing qhead::get() on an empty queue causes a run-time error. In WMODE , executing qhead::get() on an empty queue returns the NULL pointer instead of a pointer to an object .

virtual objtype o_type()

Returns object::QHEAD .

int pending()

Specifies that get operations on a queue must wait until an object is put in the queue. It returns a nonzero value if the queue attached to a qhead object is empty; otherwise, it returns 0.

void print (int verbosity, int internal_use = 0)

Prints a qhead 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.

int putback(object *new_queue_element)

Inserts at the head of the queue the object that the new_queue_element argument points to, and returns a value of 1 on success. This lets the qhead object operate as a stack (hence, the name putback ). Space must be available in the queue for it to succeed. Calling qhead::putback() for a full queue causes a run-time error in both EMODE and WMODE and returns NULL in ZMODE .

int rdcount()

Returns the current number of objects in the queue attached to a qhead object.

int rdmax()

Returns the maximum length of the queue.

qmodetype rdmode()

Returns the current mode of a qhead object, which can be EMODE , WMODE , or ZMODE .

void setmode(qmodetype modetype)

Sets the mode of a qhead object to modetype, which can be EMODE , WMODE , or ZMODE .

void setmax(int size)

Sets size as the maximum length of the queue attached to a qhead object. You can set size to a number less than the current number of objects of the object class, but that means you cannot put any more objects of the object class on the queue until the length of the queue has been reduced below the limit you set.

void splice(qtail *delete_tail)

Forms a single queue by appending a queue attached to a qhead object onto the queue referenced in the argument. Typically, this reverses the action of a previous qhead::cut() function. The extra qhead and qtail objects are deleted. Waiting tasks resume execution if merging the two creates a nonempty queue (if the task was trying to get) or an empty queue (if the task was trying to put).

qtail *tail()

Creates a qtail object for the queue attached to a qhead object (if none exists) and returns a pointer to the new qtail object.

qtail class

Abstraction for the tail of a list of items in a first-in, first-out singly linked list.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class qtail: public object 
{ 
    friend class qhead; 
 
public: 
              qtail(qmodetype modetype = WMODE, int size = 10000); 
              ~qtail(); 
 
    qtail     *cut(); 
    qhead     *head(); 
    int       put(object *new_queue_element); 
    int       rdspace(); 
    int       rdmax(); 
    qmodetype rdmode(); 
    void      setmode(qmodetype modetype); 
    void      setmax(int size); 
    void      splice(qhead *delete_head); 
 
    int       pending(); 
    void      print(int verbosity, int internal_use = 0); 
    objtype   o_type(); 
}; 

Description

This class provides facilities for putting objects into a queue. A queue is a data structure with an associated list of objects of the object class, or a class derived from the object class in first-in, first-out order. All access to a queue is through either the attached qhead or qtail object. You create a queue by creating either a qhead or a qtail object. The other end of the queue is created automatically. You can then obtain a pointer to the head with the qtail::head function.

Objects have definitions for when they are ready and pending (not ready). The qtail objects are ready when the queue is not full and pending when the queue is full.


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_PUTFULL Cannot put an object into a full queue
E_PUTOBJ Cannot put an object into queue if the object is on another queue
E_QDEL Cannot delete a queue that has an object in the queue
E_STORE Cannot allocate more memory

Constructors and Destructors

qtail(qmodetype modetype = WMODE, int size = 10000)

Constructs a qtail object. The modetype argument specifies the mode (set by the constructor) that controls what happens when an object of the qtail class is pending. The choices are WMODE (wait mode), EMODE (error mode), or ZMODE (0 mode); WMODE is the default. (See the put() function for more information.) The size argument specifies the maximum length of the queue attached to a qhead object; the default is 10,000.

The maximum size of the queue does not affect the amount of memory occupied by the queue when the queue is empty.

~qtail()

Deletes a qtail object.


Member Functions

qtail *cut()

Splits a queue into two queues. One queue has a new qtail object (to which the return value points) and the original qhead object; it contains the objects from the original queue. The other queue has the original qtail object and a new qhead object; this queue is empty. You can use this function to insert a filter into an existing queue, without changing the queue's appearance to functions that access the ends of the queue, and without halting the flow through the queue of objects.

qhead *head()

Creates a qhead object for the queue attached to a qtail object (if none exists) and returns a pointer to the new qhead object.

virtual objtype o_type()

Returns object::QTAIL .

int pending()

Specifies that get operations on a queue must wait until an object is put in the queue. It returns a nonzero value if the queue is empty; otherwise, it returns 0.

virtual void print(int verbosity, int internal_use = 0)

Prints a qtail 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.

int put(object *new_queue_element)

Adds the object denoted by the new_queue_element argument to the tail of the queue attached to a qtail object; returns a value of 1 on success. If the queue is full, the behavior depends on the mode of the qtail object. In WMODE , an object of class task that executes qhead::put() on a full queue suspends until that queue is not full. Calling qhead::put() for a full queue causes a run-time error in EMODE and returns NULL in ZMODE .

int rdspace()

Returns the number of object objects that can be inserted into the queue before it becomes full.

int rdmax()

Returns the maximum length of the queue.

qmodetype rdmode()

Returns the current mode of a qtail object, which can be EMODE , WMODE , or ZMODE .

void setmode(qmodetype modetype)

Sets the mode of a qtail object to modetype, which can be EMODE , WMODE , or ZMODE .

void setmax(int size)

Sets size as the maximum length of the queue. You can set size to a number less than the current number of objects of the object class, but that means you cannot put any more objects of the object class on the queue until the length of the queue has been reduced below the limit you set.

void splice(qhead *delete_head)

Forms a single queue by appending a queue attached to a qtail onto the queue referenced in the argument. Typically, this reverses the action of a previous qtail::cut() . The extra qhead and qtail objects are deleted. Waiting tasks resume execution if merging the two queues creates a nonempty queue (if the task was trying to get) or an empty queue (if the task was trying to put).

randint class

Objects of the randint class generate uniformly distributed random numbers.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class randint 
{ 
public: 
           randint(long seed=0); 
    int    draw(); 
    float  fdraw(); 
    void   seed(long seed); 
}; 

Description

Objects of this class generate uniformly distributed random numbers. Each random-number generator object produces a sequence that is independent of other random-number generator objects.

Constructor

randint(long seed)

Constructs an object of the randint class. The seed argument is used as the seed and is optional. Different seeds produce different sequences of generated numbers; not all seeds produce useful sequences.


Member Functions

float fdraw()

Returns the next random number generated by the object. The number is a floating-point value in the range 0 to 1.

int draw()

Returns the next random number generated by the object. The number is an integer value in the range from 0 to RAND_MAX , which is defined in the ANSI C header, stdlib.h .

void seed(long seed)

Reinitializes the object with the seed seed.

Example


 
extern "C" { 
#include <stdlib.h> 
} 
#include <task.hxx> 
#include <iostream.hxx> 
main() 
 { 
     randint gen; 
     int i=0; 
     float sum; 
     for (i=0; i<1000; i++) 
          sum += gen.fdraw(); 
     cout<<"Average is " << sum/1000. << "\n"; 
     return EXIT_SUCCESS; 
 }   
 
      

This example prints the average of 1000 floating-point random numbers.


sched class

Responsible for scheduling and for the functionality common to task and timer objects.

Header

#include <task.hxx>

Alternative Header

#include <task.h>


Declaration


class sched: public object 
{ 
public: 
    enum statetype 
    { 
        IDLE = 1, 
        RUNNING = 2, 
        TERMINATED = 4 
    }; 
 
protected: 
                 sched(); 
 
public: 
    static task  *clock_task; 
    static PFV   exit_fct; 
 
    void         cancel(int result); 
    int          dont_wait(); 
    sched        *get_priority_sched(); 
    int          keep_waiting(); 
    statetype    rdstate(); 
    long         rdtime(); 
    int          result(); 
 
    int          pending(); 
    virtual void print(int verbosity, int internal_use = 0); 
    virtual void setwho(object *alerter); 
 
    static long  get_clock(); 
    static sched *get_run_chain(); 
    static int   get_exit_status(); 
    static void  set_exit_status(int); 
    static void  setclock(long); 
}; 
 
#ifdef CXXL_DEFINE_CLOCK 
#define clock (sched::get_clock()) 
#endif 
#define run_chain (sched::get_run_chain()) 

Description

This class provides facilities for checking on the state of a task, manipulating the simulated clock, canceling a task, and checking on the result of a task.

You can create instances of classes derived from the sched class, but you cannot create instances of the sched class itself.


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_CLOCKIDLE Cannot advance the clock when the clock_task is RUNNING or TERMINATED
E_NEGTIME Cannot delay a negative amount of time
E_RESOBJ Cannot resume a task or timer if it is already on another queue
E_RESRUN Cannot resume a RUNNING task
E_RESTERM Cannot resume a TERMINATED task
E_SCHOBJ Cannot use class sched other than as a base class
E_SCHTIME Cannot execute something at a time that has already passed
E_SETCLOCK Cannot set the clock after it has advanced past 0


Member Data

static task *clock_task

Points to the task clock if one exists.

static PFV exit_fct

Points to the exit function if one exists.

Constructor

sched()

Constructs a sched object initialized to the IDLE state and delay 0.

Member Functions

void cancel(int result)

Puts an object into the TERMINATED state without suspending the caller (that is, without invoking the scheduler); sets the result of the object to result.

int dont_wait()

Returns the number of calls to keep_waiting() , minus the number of calls to the dont_wait() function, excluding the current call. The return value of this function should equal the number of objects of the object class waiting for external events before the current dont_wait() call.

long get_clock()

Returns the value of the clock in simulated time units.

int get_exit_status()

Returns the exit status of the task program. When a task program terminates successfully (without calling task_error ), the program calls exit(i) where i is the value passed by the last caller of sched::set_exit_status() .

sched *get_priority_sched()

Returns a pointer to a system task's interrupt_alerter if the system gets an awaited signal. If no interrupt occurs, this function returns 0.

sched *get_run_chain()

Returns a pointer to the run chain, the linked list of ready objects belonging to classes derived from the sched class ( task and timer objects).

int keep_waiting()

Keeps the scheduler from exiting when no tasks exist that can be run (an external event could enable an IDLE task to be run). This function should be called when the user program creates an object that waits for an external event. Afterward, when such an object destructs, a call should go to the dont_wait() function. The keep_waiting() function returns the number of calls (not counting the current call) minus the number of calls to the dont_wait() function.

int pending()

Returns 0 if the object is in the TERMINATED state; otherwise, it returns a nonzero value.

virtual void print(int verbosity, int internal_use = 0)

Prints a sched 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.

statetype rdstate()

Returns the state of the object: RUNNING , IDLE , or TERMINATED .

long rdtime()

Returns the simulated clock time at which to run the object.

int result()

Returns the result of a sched object (as set by the task::resultis() , task::cancel() , or sched::cancel() function). If the object is not yet TERMINATED , the calling task suspends and waits for the object to terminate. A task calling result() for itself causes a run-time error.

void setclock(long new_clock)

Initializes the simulated clock to a time specified by the new_clock argument. You can use this function once before the simulated clock has advanced without causing a run-time error. To advance the clock after the initial setting, call the task::delay function.

void set_exit_status(int new_exit_status)

Sets the exit status of the task program. When a task program terminates successfully (without calling task_error ), the program calls exit(i) , where i is the value passed by the last caller of sched::set_exit_status() .

virtual void setwho(object *alerter)

Records which object alerted the object. The alerter argument should represent a pointer to the object that caused the task package to alert the sched .

Macros

The C++ Class Library supplies the following macros for compatibility with older C++ class library implementations:

clock

Calls sched::get_clock() . For this macro to be defined, you must define CXXL_DEFINE_CLOCK on the command line when invoking the compiler, or in your source code before including the task package header.

run_chain

Calls sched::get_run_chain() .

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. 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.

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


Previous Next Contents Index