<html><!-- #BeginTemplate "/Templates/tmpl.dwt" --><!-- DW6 -->
<head>
<!-- #BeginEditable "doctitle" -->
<title>PTypes: unit</title>
<!-- #EndEditable -->
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="styles.css">
</head>
<body bgcolor="#FFFFFF" leftmargin="40" marginwidth="40">
<p><a href="../index.html"><img src="title-21.png" width="253" height="39" alt="C++ Portable Types Library (PTypes) Version 2.1" border="0"></a>
<hr size="1" noshade>
<!-- #BeginEditable "body" -->
<p class="hpath"><a href="index.html">Top</a>: <a href="basic.html">Basic types</a>:
unit</p>
<p>
<blockquote>
<pre class="lang">#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();
}</pre>
</blockquote>
<p><span class="lang">Units</span> represent functionality similar to console
applications in UNIX. Each unit has its own <span class="lang">main()</span> along
with input and output 'plugs' - <span class="lang">uin</span> and <span class="lang">uout</span>,
that may be mapped to the standard input and output, a local pipe or any other
stream compatible with <span class="lang">instm</span> and <span class="lang">outstm</span>,
respectively. </p>
<p>Each unit class must at least override the abstract method <span class="lang">main()</span>.
Overridden unit classes typically read input data from <span class="lang">uin</span>
and send the result of processing to <span class="lang">uout</span>, like if they
were console applications. By default <span class="lang">uin</span> and <span class="lang">uout</span>
are attached to standard input and output. After instantiating a unit object you
(the user of a unit class) may attach any <span class="lang">instm</span>-compatible
stream to <span class="lang">uin</span> and any <span class="lang">outstm</span>-compatible
stream to <span class="lang">uout</span>. In addition, units are able to connect
to each other using local pipes, and thus form data processing chains within your
application.</p>
<p>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).</p>
<p>Units can be run either synchronously or asynchronously. In the latter case,
a separate thread is created for executing unit's <span class="lang">main()</span>
function. If connected to a pipe using <span class="lang">connect()</span>, the
first unit in the chain runs within the scope of the calling thread, the others
run in separate threads.</p>
<p>The <span class="lang">unit</span> class is a subclass of <a href="unknown.html">component</a>,
and thus it inherits reference counting and delete notification mechanisms from
<span class="lang">component</span>. <span class="lang">Unit</span> is declared
in <a href="include/pstreams.h.html"><pstreams.h></a>.</p>
<p>This interface is available only in the multithreaded versions of the library.
</p>
<p><span class="def">compref<instm> unit::uin</span> is a reference-counted
pointer to an input stream, that is unit's input 'plug'. By default <span class="lang">uin</span>
refers to the standard input object <span class="lang">pin</span>. Typically both
<span class="lang">uin</span> and <span class="lang">uout</span> are assigned
by the user of the unit after instantiating a unit object. You may assign dynamically
allocated stream objects to <span class="lang">uin</span> and <span class="lang">uout</span>
- they will be freed automatically by the 'smart' <span class="lang">compref</span>
pointer.</p>
<p><span class="def">compref<outstm> unit::uout</span> -- same as <span class="lang">uin</span>;
represents the output 'plug' of the unit.</p>
<p><span class="def">virtual void unit::main()</span> is unit's main code. Override
this method to implement functionality of your mini-process. Note that code in
<span class="lang">main()</span> 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 <span class="lang">main()</span> can be called multiple times for the
same object, however <span class="lang">main()</span> is protected from overlapping
(recursive) calls, which means, you need not to write reentrant code in this function.</p>
<p><span class="def">virtual void unit::cleanup()</span> -- override this method
to perform finalization and cleanup of a unit. This function is guaranteed to
be called even if <span class="lang">main()</span> threw an exception of type
<span class="lang">(exception*)</span> or a derivative.</p>
<p><span class="def">void unit::connect(unit* next)</span> connects a unit object
to another object using a local pipe. Multiple units can be connected to form
a chain. A user then calls <span class="lang">run()</span> for the first object;
all other members of the chain are started automatically in separate threads.</p>
<p><span class="def">void unit::run(bool async = false)</span> runs a unit object.
This function calls <span class="lang">main()</span> for the given object and
possibly for other units, if this is the first object of a chain. You can not
call <span class="lang">run()</span> for an object which is not the first in a
chain. If <span class="lang">async</span> is <span class="lang">true</span>, this
function starts a unit in a separate thread and returns immediately. Use <span class="lang">waitfor()</span>
to synchronize with the completion of a unit if started asynchronously.</p>
<p><span class="def">void unit::waitfor()</span> 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.</p>
<p><b>Example</b>. Consider there is a unit type <span class="lang">ugrep</span>
that performs regular expression matching and a unit type <span class="lang">utextconv</span>
for converting various text formats. The code below demonstrates how to connect
these units and run the chain.</p>
<blockquote>
<pre>#include <pstreams.h>
#include "ugrep.h" <span class="comment">// imaginary headers with unit declarations</span>
#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;
<span class="comment">// connect the two units and set up the input and output plugs.
</span> grep.uin = new ipstream("somehost.com", 8282);
grep.connect(&textconv);
textconv.uout = new outfile("output.txt");
<span class="comment">// now run the chain; will read input from the socket, pass
// through the grep and textconv units and write it to the
// output file.</span>
grep.run();
}
</pre>
</blockquote>
<p class="seealso">See also: <a href="unknown.html">unknown & component</a>,
<a href="streams.html">Streams</a> </p>
<!-- #EndEditable -->
<hr size="1">
<a href="../index.html" class="ns">PTypes home</a>
</body>
<!-- #EndTemplate --></html>