CAPS Universe documentation  1.0.4
All you need to know to be successful
Data Structures | Functions
Multi core processing framework

Multithread framework to improve data processing. More...

Data Structures

struct  caps_worker_idx
 Declaration of the callbacks. More...
 

Functions

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)
 
int caps_worker_idx_start (struct caps_worker_idx_context *wctx)
 
void caps_worker_idx_stop (struct caps_worker_idx_context *wctx)
 

Detailed Description

Collection of helper functions to improve page processing speed by spreading the work to multiple CPU cores.

Main precondition to make use of this framework is, the print data send to the printer must be split into individual sub-pieces. Each set of these individual pieces get a unique index and then the Index Worker can be run on these pieces to process them. What has to be done to process them is up to the printer and the printer driver author.

The precondition to make use of this worker is, you must be able to split the raw raster data into pieces which can be processed independently (e.g. conversion from raw raster data into the printer's wire data). For example some laser printer expect their wire data in pieces of a specific amount of lines (128 lines at once for example). Thus, the whole raster can be split into n pieces of 128 lines raster data in this case until the full raster is done. How you organize it is up to you.

Note
Processing the print data and sending it to the printer are separate jobs!

Index Worker

This index worker runs thread_cnt + 1 threads to call the caps_worker_idx::idx_process() once for each index in the range of 0 … index_cnt - 1. The index_no parameter defines the piece of data to process. When processing is done, you need to remember somehow this index is already finished. After returning, the worker calls the caps_worker_idx::idx_is_ready() callback and checks for a specific index. If the index is already finished the index worker will call caps_worker_idx::idx_send() to send the result of this index to the printer.

Note
The calling thread is used to process the indices as well. Thus, while running, thread_cnt + 1 threads are running

In the example below thread_cnt is one. Whenever the main thread is idle (e.g. cannot call caps_worker_idx::idx_send() because there is no already processed data waiting), it calls caps_worker_idx::idx_process(), too.

While calling caps_worker_idx::idx_process() is done in any index order and for different indices at a time, calling caps_worker_idx::idx_send() is done in ascending index order.

This functions returns, when caps_worker_idx::idx_process() is finally called once for each index number and the same for caps_worker_idx::idx_send().

Warning
Since at the same time at least two raster data sets are processed concurrently, you may need much more memory doing so. Keep this in mind.

Function Documentation

◆ caps_worker_idx_create()

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 
)

Create a new index worker context

Parameters
[out]wctxWhere to store the new worker context
[in]ciwThe callbacks into the page processor
[in]anonymous_dataThe anonymous data used for the callbacks
[in]index_cntThe count of indices to handle in this worker (> 1 and <= INT_MAX)
[in]thread_cntThe amount of additionally used threads
Return values
0On success, *wctx is valid
-EINVALindex_cnt below '2' or above INT_MAX
NegativeErrno, *wctx is invalid
Note
thread_cnt can be '0', but internally '1' will be used instead in this case.
Precondition
Since the index number is the sole indicator what has to be processed or be sent to the printer, the client of this function needs to transform the index number into its own data structures (via anonymous_data for example).
Since the threads will do plain data processing, it makes less sense to start more threads than CPU cores are available. Refer #get_nprocs() to detect the available and active CPU cores and select thread_cnt one less of the returned CPU core count. E.g. three, if you have four CPU cores.
Postcondition
After the job is done, call caps_worker_idx_destroy() to free the resources

◆ caps_worker_idx_destroy()

void caps_worker_idx_destroy ( struct caps_worker_idx_context wctx)

Destroy an index worker context

Parameters
[in]wctxIndex worker context
Precondition
Can be called after caps_worker_idx_start() returned.

◆ caps_worker_idx_start()

int caps_worker_idx_start ( struct caps_worker_idx_context wctx)

Run a multithreaded index helper to convert raw raster data into printer's wire data piece wise

Parameters
wctxIndex worker context to use
Return values
0On success. Every index is processed and every index is sent to the printer
NegativeErrno

In case of an error, all threads are guaranteed to be stopped again.

Note
This call only returns if everything is processed, on an asynchronous termination request via caps_worker_idx_stop() or an error happens.
Precondition
A valid index worker context, already created by caps_worker_idx_create()
Postcondition
After it returns, it is safe to call caps_worker_idx_destroy() to clean up everything worker related. You are responsible to clean up your own data allocated in conjunction to this worker.

◆ caps_worker_idx_stop()

void caps_worker_idx_stop ( struct caps_worker_idx_context wctx)

Stop an already running worker asynchronously

Parameters
wctxIndex worker context to stop

When this call returns each worker thread ends its current work and then begins to terminate. The same is valid for the main worker thread and after that the call to caps_worker_idx_start() returns.

Note
This call is intended to be called from within a signal handler asynchronously.