PREV UP NEXT StackThreads/MP: version 0.77 User's Guide

6.2.1: Create a Worker Group

StackThreads/MP provides a convenient way to create a worker group that executes a given StackThreads/MP procedure (stf_create_sync_worker_group and stf_create_async_worker_group). They serve as gates from a sequential procedure to any StackThreads/MP procedure. They create a specified number of workers, setup pointers to the worker local storages, and then call the specified entry procedure. The entry procedure is a StackThreads/MP procedure and thus is allowed to access any StackThreads/MP primitives.

        void* stf_create_sync_worker_group(wgc, n, f, a0, a1, a2, a3)
@                worker_group_conf_t wgc; int n;
@                void * (*f)(void *, void *, void *, void*);
@                void * a0, * a1, * a2, * a3;

workers. The job of the worker group is given by an entry procedure f and arguments to it (a0 ... a3). Specifically, the worker group's job is to complete a procedure call f(a0, a1, a2, a3). stf_create_sync_worker_group returns when f(a0, a1, a2, a3) returns. The return value of f(a0, a1, a2, a3) becomes the return value of the stf_create_sync_worker_group. If non-zero value is given to wgc, it is a pointer to a structure that describes configuration options of the worker. If wgc is zero, a default configuration is used. stf_create_sync_worker_group can be called both from a sequential procedure and from a StackThreads/MP procedure. If you call this procedure from a sequential module (a module that is compiled by plain gcc), include <st_foreign.h>, which defines the correct prototype for the procedure.

For example, suppose you are writing an X Window application and wish to add a callback function that uses StackThreads/MP primitives. Also assume that you don't want to recompile the Xlib or your administrator didn't allow you to replace nor duplicate it, thus the Xlib itself must remain sequential. In this case, you first write a StackThreads/MP procedure that accomplishes your job.

... my_st_proc(...)
{
@  /* do whatever you can do with 
@     StackThreads/MP */
@  ST_THREAD_CREATE(...);
@    ...
@  ST_THREAD_CREATE(...);
@    ...
}

You may want to write a wrapper procedure of the above function, so that the entry procedure conforms to the interface of stf_create_sync_worker_group. The wrapper's job is simply to pass parameters to the above procedure, possibly casting them to meaningful types. It must be a StackThreads/MP procedure.

void * my_st_proc_wrapper(void * a0, void * a1, void * a2, void * a3)
{
@    /* you translate arguments somehow */
@    ...
@    /* and call my_st_proc to do a real job */
@    my_st_proc(...);
}

Finally, you write a callback procedure that invokes the entry procedure and registers it. This must be a sequential procedure (compiled by a plain C compiler), because X library calls that procedure.

void my_callback(...)
{
@  int n = ...;
@  void * a0 = ..., * a1 = ..., 
@       * a2 = ...; * a3 = ...;
@  stf_create_sync_worker(0, n, my_st_proc_entry, a0, a1, a2, a3);
}
@
@  ...
@  XAddCallback(my_callback, ...);
@  ...

stf_create_async_worker is an asynchronous version of stf_create_sync_worker. See Workers and Worker Groups for details.