Basicaly, purpose of this library is to provide suffiscient mechanisms to handle independant data streams of different kind in asynchronous interactive processes (called data handlers) over a network.
This implies :
This library has been set up to use with the libWhisper library.
nrtThread class defines a process (method) that be threaded. This
is an abstract class since the threaded method,
execute(void *), is
When this class is derived, it is expected that either
createDetached(void *) is called explicitly (e.g. in the
create makes a joinable thread, and
createDetached a detached one.
In both cases, the th protected variable holds the last created thread identifier.
nrtThread holds a internal synchronisation variable that can,
directly or not, used through the
kill(nrtThread *) (current thread
activates de conditional variable of the given thread) and
wait(pthread_cond_t *_cond = 0) (current thread is waiting for the
activation of a synchronisation variable, its own by default) methods.
nrtCyclicThread (inherited from
nrtThread) has a special
behaviour; it calls the virtual
handle(void) method periodicaly.
Secs(void) to access period.
The internal EOT parameter has to be set to 1 whenever the thread has to be killed.
Classical mutex is provided by the
rtMutex class. It got essentialy
two accesors :
P(void) (pick the ``token'') and
rtRecursiveMutex (that inherits from
rtMutex class) allows
a predefined number of ``token'' to be picked at a time. Number is an
optional argument to class's constructor (default is 16).
A shared data can be written by one writer, at a time, or readen by many
readers. Basic operations are provided by
Readers(void) method give the reader's number, and
DirectReaders(void) does the same thing without implicitly
assuming any other concurent access (this can be useful precautions have
been taken by programmer). Anyway, those methods are situated at a very
low level, and you probably won't care.
rtSharedInt holds a single shared integer that can be read using
DirectValue(void) methods, and sets
set(int _value) or prefixed
A paramater (
rtParameter class) has following protected char* members:
Accessors have same name, with an upcased first character.
rtIntegerParameter is derived from
rtSharedInt and can be cloned using the
rtIntegerParameter *clone(void) method.
It appears that a intermediate class could introduce a more flexible implementation.
rtParameters defines a fixed number of pointers to some parameters.
You'll probably need the
GetInt(char *_name) methods to handle parameters.
rtSocket defines a standard socket and provides tree important
void send(char *buffer, int _length);,
void recv(char **buffer, int _length); and
void recv(char *buffer, int _length);.
It is used as the base of following classes; they all use the TCP network protocol.
rtSocketClient is used to connect to an
IPC server. Connection is made using the
void connect(char *_addr, int _port); method.
Remember that this class inherits
rtSocketServer can be used as IPC minimal server. It adds to
rtSocket methods the protected and purely virtual
void handleClient(rtSocket *_socket) method.
rtStreamWriterSocket waits for clients, encodes incoming data
stream, and sends it to all connected clients, via different sockets.
For now, four clients can be connected simultaneously.
void handleSound(rtDataStreamBlock *block) has probably to be
adapted to particular uses.
rtStreamReaderSocket constructor allows connecting to any instance
rtStreamWriterSocket, then incoming data are handled
in rtDataHandler's `handle' familly methods (for instance
void handleSound(rtDataStreamBlock *block)).
WHISPER has a specific way to handle data. That means that both computing processes and data are some pre-defined WHISPER's objects.
A data handler (that processes data) has incoming and outgoing data streams
that consists of data blocks. Futhermore, each data handler is hold by a
whisperChain); introducing therefore another level of
Whenever a incoming block arrives, handler (which is a thread) is signaled,
and increments its
waitingBlocks shared variable. Then, each block
is readen through the incoming data stream's
and forwarded to one of the
A data block is a typed array of characters with arbitrary length. Since
each data block can be read asynchronously by data handlers (inherited from
nrtThread), it has to be aware of the number of future reading
that are left.
When a block isn't useable anymore by any of its reading handlers, it is automaticaly deleted from the stream its belong to.
In WHISPER, a data stream consists of ordered independant data stream blocks.
Few methods are available to handle streams :
chain(int _type, char *_buffer, int _length) and
*chain(rtDataStreamBlock *) allows programmer to chain a new block
into the stream.
readNext(rtDataStreamBlock *) returns the block following the given
block. But it hasn't to be called directly by programmer.
Some other facilities are providen to compute stream rate and such things.
A chain can hold many dependant data handlers. It has a name, and some convenience methods to report messages or errors.
whisperChain class inherits
executes a virtual
handle(void) method periodicaly. By default,
this method does nothing.
In brief, a WHISPER application (
whisperApplication) is a
nrtCyclicThread that can manage some WHISPER chains.
Most important providen methods are probably
setCurrentToLast(void) and the message handling methods.
First of all, the application must instanciate a chain, using
addChain(char *_name) and declare it as default chain
addHandler(rtDataHandler *) can be called and any
new handler'll go in the default chain.