The thread pool functions
Now that we have a good feel for how the number of threads is controlled, let's turn our attention to the other members of the thread pool attribute structure (from above).
// thread pool functions and handle
THREAD_POOL_HANDLE_T *handle;
THREAD_POOL_PARAM_T *(*block_func)(THREAD_POOL_PARAM_T *ctp);
void (*unblock_func)(THREAD_POOL_PARAM_T *ctp);
int (*handler_func)(THREAD_POOL_PARAM_T *ctp);
THREAD_POOL_PARAM_T *(*context_alloc)(THREAD_POOL_HANDLE_T *handle);
void (*context_free)(THREAD_POOL_PARAM_T *ctp);
#include
<sys/resmgr.h> before
<sys/dispatch.h>.
Recall from the diagram Thread flow when using thread pools,
that the
context_alloc() function gets called for every new thread being created.
(Similarly, the context_free() function gets called for every thread being
destroyed.)
The handle member of the structure (above) is passed to the context_alloc() function as its sole parameter. The context_alloc() function is responsible for performing any per-thread setup required and for returning a context pointer (called ctp in the parameter lists). Note that the contents of the context pointer are entirely up to you—the library doesn't care what you put into the context pointer.
Now that the context has been created by context_alloc(),
the block_func() function is called to perform the blocking operation.
Note that the block_func() function gets passed the results of the
context_alloc() function.
Once the block_func() function unblocks, it returns a context pointer, which gets
passed by the library to the handler_func().
The handler_func() is responsible for performing the work
—for example,
in a typical server, this is where the message from the client is processed.
The handler_func() must return a zero for now—nonzero values are reserved
for future expansion by QNX.
The unblock_func() is also reserved at this time; just leave it as
NULL.
Thread flow when using thread pools,above):
FOREVER DO
retval = (*block_func) (context);
IF (#threads < lo_water) THEN
IF (#threads_total < maximum) THEN
create new thread
context = (*context_alloc) (handle);
ENDIF
ENDIF
(*handler_func) (retval);
IF (#threads > hi_water) THEN
(*context_free) (context)
kill thread
ENDIF
DONE
Note that the above is greatly simplified; its only purpose is to show you the data flow of the ctp and handle parameters and to give some sense of the algorithms used to control the number of threads.