United States

Compaq C++

# Compaq C++
Class Library Reference Manual

Previous | Contents | Index

The first line of this example provides a character string to the constructor for initialization. The overloaded operators (!=, <<, and =) accept either two `String` objects or a `String` and a null-terminate sequence of characters. The last line prints out the following character string:

    Pink Triangles

#2
    String x ("The Times of John Doe");

    String a (x(18,3));    // Substring is "Doe"
    String b (x);          // b contains all of x

> In this example, the creation of object `a` provides a substring of object `x` to the constructor for object `a` . The substring begins at position 18 and has a length of 3 characters. The next line creates the object `b` and initializes it to contain the same value as `x` .

#3
    String x ("World");
    String y;

    y = "Hello";
    y += ", " + x + ".\n";

    cout << y;

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

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

Previous | Next | Contents | Index

privacy and legal statement