DIGITAL logo   C++ Graphic
    Updated: 21 April 1999
  DEC C++

DEC C++
Class Library Reference Manual


Previous Contents Index

This example shows string concatenation. The last line prints out the following message:


Hello, World. 


Chapter 10
task Package

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.

To ensure that all necessary libraries are linked into the executable program image, certain switches need to be provided to the linker through the cxx command. For detailed information on the switches to use, see Using Compaq C++ for Tru64 UNIX.


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 Supplementary Documents Vol II, which is part of the Digital UNIX documentation.


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 signals, establishing a signal handler when the thread system initializes. Initialization normally occurs at instantiation of the first task object; however, a program could also invoke this initialization directly, before the task package does. Knowledge of any signal handlers established by the program prior to initialization is lost.

Whenever an Interrupt_handler object is created for a signal, the interrupt handler saves the previous handler for that signal.

If the program subsequently establishes a new handler for a signal, the interrupt handler does not operate until the program reestablishes the interrupt handler's signal handler (which is returned to the program when the program calls the signal function to take control of that signal).

When the last Interrupt_handler object is destroyed for a signal, the interrupt handler restores the signal handler that was in effect when the first Interrupt_handler object was created for that signal. This is the thread system signal handler.

Because signals affect all threads of the process, be cautious when establishing signal handlers or creating interrupt handlers. Some signals are used by the thread system for time slicing. Some language run-time libraries or other facilities may also establish signal handlers.


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.


Previous Next Contents Index

   
Burgundy bar
DIGITAL Home Feedback Search Sitemap Subscribe Help
Legal