CAPS Universe documentation  1.0.4
All you need to know to be successful
Data Structures | Functions
worker_index.c File Reference

Process in parallel based on indices. More...

Data Structures

struct  caps_worker_idx_context
 Index worker internal tracking data. More...
 

Functions

void caps_worker_idx_stop (struct caps_worker_idx_context *wctx)
 
static int idx_terminate (struct caps_worker_idx_context *wctx)
 
static int idx_next_to_process_get (struct caps_worker_idx_context *wctx)
 
static void idx_mark_done (struct caps_worker_idx_context *wctx)
 
static unsigned idx_already_done_get (struct caps_worker_idx_context *wctx)
 
static void idx_already_done_get_with_wait (struct caps_worker_idx_context *wctx)
 
static void * worker_thread (void *p)
 
static pthread_t create_worker_thread (void *param)
 
int caps_worker_idx_create (struct caps_worker_idx_context **wctx, const struct caps_worker_idx *ciw, void *anonymous_data, unsigned index_cnt, unsigned thread_cnt)
 
void caps_worker_idx_destroy (struct caps_worker_idx_context *wctx)
 
static bool idx_done_check (struct caps_worker_idx_context *wctx)
 
static bool idx_left_to_print_check (struct caps_worker_idx_context *wctx)
 
static void worker_idx_print (struct caps_worker_idx_context *wctx)
 
int caps_worker_idx_start (struct caps_worker_idx_context *wctx)
 

Function Documentation

◆ idx_terminate()

static int idx_terminate ( struct caps_worker_idx_context wctx)
static

Query the termination state

Parameters
[in]wctxWorking context
Return values
0Continue
1Terminate

◆ idx_next_to_process_get()

static int idx_next_to_process_get ( struct caps_worker_idx_context wctx)
static

Get the next index to process

Parameters
[in,out]wctxWorking context
Return values
PositiveIndex to process [0…n]
-ENODATANo more indices to process

Called by all worker threads

This index works like a lock. As long the thread works on this index, it owns it and its corresponding status info

Note
The first call must return the index '0'
Postcondition
On error (including the -ENODATA) the thread just terminates immediately

◆ idx_mark_done()

static void idx_mark_done ( struct caps_worker_idx_context wctx)
static

Signal another index is now processed

Parameters
[in,out]wctxWorking context

Called by the worker thread when it has processed an index

◆ idx_already_done_get()

static unsigned idx_already_done_get ( struct caps_worker_idx_context wctx)
static

Retrieve if at least one index is available (e.g. already processed and ready to print)

Parameters
[in,out]wctxWorking context
Return values
1Yes, an already done index is available
0No, no index is available

Called by the main worker thread. This call never sleeps

Note
On a semaphore error this routine will terminate the worker

◆ idx_already_done_get_with_wait()

static void idx_already_done_get_with_wait ( struct caps_worker_idx_context wctx)
static

Retrieve if at least one index is available (e.g. already processed and ready to print)

Parameters
[in,out]wctxWorking context

Called by the main worker thread. This call sleeps if the semaphore is still '0'

Note
On a semaphore error this routine will terminate the worker

◆ worker_thread()

static void * worker_thread ( void *  p)
static

Index processing worker thread

Parameters
[in]pThe working context

This worker thread loops until there are no more indices to process.

Since this thread should only work on plain data, it should not be involved into signal processing. This should be limited to the main worker thread only.

I have no idea how to setup this in a race free manner. This thread inherits the signal mask from the main worker thread. So we can't mask the signals in the main worker thread because that would interfere with the programmer's settings. So, change the signal's mask here, prior starting to work on real data.

TODO The solution could be to create a separate thread only for receiving the signals. Refer sigwaitinfo() for details. The manual page for pthread_sigmask() contains an example.

  • block all signals
  • create the separate signal thread
  • in this signal thread enable all signals and wait for them
  • all other threads are now "signal free" -> we need to instruct the programmer to Do the right thing -> but it still may conflict with his own requirements....

    Todo:
    glibc-2.36 comes with a new function to set the mask when creating a thread. Make use of it.

◆ create_worker_thread()

static pthread_t create_worker_thread ( void *  param)
static

Create one thread to process indecs according to our local requirements

Parameters
[in]paramMust be a pointer to the current context
Returns
The ID of this worker thread
Todo:
Fix exit() usage in create_worker_thread()

◆ idx_done_check()

static bool idx_done_check ( struct caps_worker_idx_context wctx)
static

Check if the next index to print is already processed

Parameters
[in,out]wctxWorking context
Return values
trueUser's callback reports processing done
falseUser's callback reports processing is ongoing

Its up to the user to decide if an index is already done.

◆ idx_left_to_print_check()

static bool idx_left_to_print_check ( struct caps_worker_idx_context wctx)
static

Check, if there are still indices left to print

Parameters
[in,out]wctxWorking context
Return values
falseIf there are not more indices left to print
trueIf there are still more indices left to print

◆ worker_idx_print()

static void worker_idx_print ( struct caps_worker_idx_context wctx)
static

Call the printing callback as often as possible

Parameters
[in,out]wctxWorking context

Print as much already done consecutive indices as possible. This is required to avoid a dead-lock, because the corresponding semaphore events for the indices following the current one may be already consumed: we must make up for them.