This section assumes a knowledge of the basic concepts in section Overview of `TOP-C/C++'.
Every `TOP-C' application must include a `topc.h' header, open
with TOPC_init()
, call TOPC_master_slave()
one or more
times, and then close with TOPC_finalize()
.
#include <topc.h>
Required at head of any file using TOPC library calls.
TOPC_master_slave()
;
Recommended to place this as first executable statement in
main()
. It will strip off extra `TOP-C' and
communication layer arguments such as --TOPC-verbose
,
which are added by `TOP-C'.
TOPC_master_slave()
, each invoking different callback functions,
between TOPC_init()
and TOPC_finalize()
.
A task input or task output is simply a buffer of bytes, specified by
TOPC_MSG()
.
GenerateTaskInput()
and DoTask()
.
Specifies arbitrary user data structure.
`TOP-C' will make a copy of buf in `TOP-C' space.
It remains the responsibility of the application to free or
reuse the space of the original buffer buf. If
TOPC_MSG(NULL, 0)
is called, a NULL
pointer will be
received at the destination.
(See section Using TOPC_MSG_PTR()
to Avoid Copying Large Buffers, for TOPC_MSG_PTR
,
to avoid copying very large buffers, where the overhead is
unacceptable.)
EXAMPLE:
TOPC_BUF convert_string_to_msg( char *mystring ) { if (mystring == NULL) return TOPC_MSG(NULL,0); else return TOPC_MSG(mystring, strlen(mystring)+1); }
TOPC_master_slave()
The application writer must define the following four callback
functions (although the last can be NULL
). The first two
functions return a TOPC_BUF
, which is produced by TOPC_MSG()
.
TOPC_MSG(buf, buf_size)
.
It should return NOTASK
, when there are no more tasks, and it
should be prepared to return NOTASK
again if invoked again.
GenerateTaskInput()
;
returns a data structure specified by
TOPC_MSG(buf, buf_size)
.
buf must be a static or global user buffer.
DoTask()
;
returns an ACTION that determines what happens to the task next.
The terminology result refers to an `(input, output)' pair.
An easy way to write CheckTaskResult()
appears in the
example for the utility TOPC_is_up_to_date()
.
This function can modify the input and to output buffers,
and the modifications will persist upon calling REDO
,
UPDATE
or CONTINUATION()
.
See section TOP-C Utilities, for more details.
DoTask()
, and the original task returned by
GenerateTaskInput()
;
called only if CheckTaskResult()
returned UPDATE
;
useful for updating non-shared, global variables in all processes;
The pointer argument, update_shared_data, may be NULL
if
an application never requests an UPDATE
action.
In a shared memory environment, only the master calls
UpdateSharedData()
. See section Optimizing TOP-C Code for the Shared Memory Model, for more details.
Note that in defining the above callback functions, C allows one to replace
the (void *)
declartion of the arguments by specific
pointer types.
CheckTaskResult()
A TOP-C result is an (input, output) pair corresponding
to an invocation of DoTask()
. `TOP-C' passes the result to
CheckTaskResult()
. The return value allows the application to
tell `TOP-C' what further actions to take.
The actions returned by CheckTaskResult()
are:
UpdateSharedData( void *input,
void *output)
(see below)
also updates bookkeeping for sake of TOPC_is_up_to_date()
(see section TOP-C Utilities)
DoTask()
on original task input again, and on
the same slave that previously executed the task; useful if
shared data has changed since original
invocation of DoTask()
(see TOPC_is_up_to_date()
,
below). See section Strategies for Greater Concurrency,
for slave strategies to efficiently process a REDO
action.
CONTINUATION(next_input)
is a parametrized action that
may be returned by CheckTaskResult()
, after which
DoTask( next_input )
is called on the original slave.
This is useful if only the master can decide whether task is complete,
or if the master wishes to supply additional input messages
needed for the task.
Note that REDO
is essentially equivalent to
CONTINUATION( original_task_input )
.
Note that any pending calls to UpdateSharedData()
will have
occurred on the slave before the new call to DoTask()
.
Hence, this allows an extended conversation between master and
slave, in which the slave continues to receive updates of the
shared data before each new input from the master.
Note also that even though a CONTINUATION
action returns
to the original slave, any previous pointers to input buffers
on that slave
(and pointers to output buffers from intervening UPDATE
actions) will no longer be valid. Useful data from previous buffers
should have been copied into global variables on the slave.
In the case of the shared memory model, those global variables must be
thread-private. (see section Thread-Private Global Variables)
It is possible for CheckTaskResult(input, output)
to
modify the buffer data in its two arguments, input and output,
in which case the modifications will be visible to any further
callback functions processing the current task. This practice makes
the code more difficult to maintain, and is not recommended when other
solutions are available.
`TOP-C' also defines some utilities.
CheckTaskResult()
has not returned the result UPDATE
(invoking
UpdateSharedData()
)
between the time when GenerateTaskInput()
was originally
called on the
current task, and the time when the corresponding
CheckTaskResult()
was called.
Typical usage:
TOPC_ACTION CheckTaskResult( void *input, void *output ) { if (input == NULL) return NO_ACTION; else if (TOPC_is_up_to_date()) return UPDATE; else return REDO; }
TOPC_rank() == 0
.
TOPC_num_slaves() + 1
.
Other more specialized utilities can be found in section Advanced Features of `TOP-C'.
Go to the first, previous, next, last section, table of contents.