Top: Basic types: unit

>     #include <pstreams.h>

>     class unit {
>         compref<instm> uin;
>         compref<outstm> uout;

>         virtual void main() = 0;
>         virtual void cleanup() = 0;

>         void connect(unit* next);
>         void run(bool async = false);
>         void waitfor();
>     }

Units represent functionality similar to console applications in UNIX. Each unit has its own main() along with input and output 'plugs' - uin and uout, that may be mapped to the standard input and output, a local pipe or any other stream compatible with instm and outstm, respectively.

Each unit class must at least override the abstract method main(). Overridden unit classes typically read input data from uin and send the result of processing to uout, like if they were console applications. By default uin and uout are attached to standard input and output. After instantiating a unit object you (the user of a unit class) may attach any instm-compatible stream to uin and any outstm-compatible stream to uout. In addition, units are able to connect to each other using local pipes, and thus form data processing chains within your application.

You may define other public methods or fields in your unit class that represent additional options. E.g. a regular expression parser unit may have a string field that represents the regular expression itself (see example below).

Units can be run either synchronously or asynchronously. In the latter case, a separate thread is created for executing unit's main() function. If connected to a pipe using connect(), the first unit in the chain runs within the scope of the calling thread, the others run in separate threads.

The unit class is a subclass of component, and thus it inherits reference counting and delete notification mechanisms from component. Unit is declared in <pstreams.h>.

This interface is available only in the multithreaded versions of the library.

compref<instm> unit::uin is a reference-counted pointer to an input stream, that is unit's input 'plug'. By default uin refers to the standard input object pin. Typically both uin and uout are assigned by the user of the unit after instantiating a unit object. You may assign dynamically allocated stream objects to uin and uout - they will be freed automatically by the 'smart' compref pointer.

compref<outstm> unit::uout -- same as uin; represents the output 'plug' of the unit.

virtual void unit::main() is unit's main code. Override this method to implement functionality of your mini-process. Note that code in main() must avoid accessing static/global data, since it may be executed in a separate thread. You may choose to write a reusable unit, i.e. when main() can be called multiple times for the same object, however main() is protected from overlapping (recursive) calls, which means, you need not to write reentrant code in this function.

virtual void unit::cleanup() -- override this method to perform finalization and cleanup of a unit. This function is guaranteed to be called even if main() threw an exception of type (exception*) or a derivative.

void unit::connect(unit* next) connects a unit object to another object using a local pipe. Multiple units can be connected to form a chain. A user then calls run() for the first object; all other members of the chain are started automatically in separate threads.

void unit::run(bool async = false) runs a unit object. This function calls main() for the given object and possibly for other units, if this is the first object of a chain. You can not call run() for an object which is not the first in a chain. If async is true, this function starts a unit in a separate thread and returns immediately. Use waitfor() to synchronize with the completion of a unit if started asynchronously.

void unit::waitfor() waits for the unit to terminate if run asynchronously. For unit chains, this method needs to be called only for the first object in a chain.

Example. Consider there is a unit type ugrep that performs regular expression matching and a unit type utextconv for converting various text formats. The code below demonstrates how to connect these units and run the chain.

>     #include <pstreams.h>

>     #include "ugrep.h"        // imaginary headers with unit declarations
>     #include "utextconv.h"

>     USING_PTYPES

>     int main()
>     {
>         ugrep grep;
>         grep.regex = "^abc";
>         grep.casesens = false;

>         utextconv textconv;
>         textconv.from = CONV_UNIX;
>         textconv.to = CONV_WIN;

>         // connect the two units and set up the input and output plugs.
>         grep.uin = new ipstream("somehost.com", 8282);
>         grep.connect(&textconv);
>         textconv.uout = new outfile("output.txt");

>         // now run the chain; will read input from the socket, pass
>         // through the grep and textconv units and write it to the
>         // output file.
>         grep.run();
>     }

See also: unknown & component, Streams

PTypes home