#ifndef _aplmt_os_workersapi_h_ #define _aplmt_os_workersapi_h_ /*---------------------------------------------------------------------------- ** SUMMARY: Thread Workers Pool API (TWRKPOOL) ** ** DESCRIPTION: ** This file provides an interfaces for creating, and managing pools of ** individual worker-threads. The concept is that I have pool of pre-created ** threads that the application can 'dispatch' a chunk of work to. When the ** a worker thread has completed it automatically returns itself to the pool ** ** RESOURCES: ** ----------- ** The Worker Pool communicates with individual Thread Workers via each ** thread's Thread Semaphore. When a Thread Worker is performing 'work' ** it may use the Thread Semaphore synchronously without effecting this ** interface. The Thread Semaphore can also be used asynchronously IF ** the application guaranties that the asynchronous signals ONLY occur ** while the Thread Working is 'working' - not before or after the ** Thread Worker is dispatched. ** ** ** CONFIGURATION ** ------------- ** COMPILE: USE_APLMT_TWRKPOOL_LINKABLE_POOLS ** USE_APLMT_TWRKPOOL_ENABLE_WORKERS_TERMINATE ** ** APPLICATION: none. ** ** PLATFORM: none. ** ** NOTES: ** 1. Unless explicitly stated otherwise, NONE of the following methods may be ** called from interrupt service routines. ** 2. Unless explicitly stated otherwise, NONE of the following methods may be ** called before the platform's kernel is running. ** 3. Unless explicitly stated otherwise, all of the following methods ARE ** thread-safe. ** 4. For efficency/optimization some methods are 'inlined'. The inlining ** is done by using the preprocessor/macros. The application should ** treat all methods as function calls and not rely on the fact they may ** be currently defined as macros. ----------------------------------------------------------------------------*/ #include "aplcfg.h" /* For: Application configuration */ #ifdef __cplusplus extern "C" { #endif /*-------------- TYPES -----------------------------------------------------*/ /** Function type/definition for executing a unit-of-work */ typedef void (*AplmtUnitOfWorkFunc)(void*); /** Node Structure that identifiers a worker thread */ #define AplmtThreadWorker _AplmtThreadWorker /** Handle to a worker thread */ #define AplmtThreadWorkerHdl AplmtThreadWorker* /** Thread Worker Pool. Note: Worker Pools can be contained in AplSList or AplDList linked lists. This feature is enabled by the switch: USE_APLMT_TWRKPOOL_LINKABLE_POOLS */ #define AplmtThreadWorkerPool _AplmtThreadWorkerPool /** Handle to a Thread Worker Pool */ #define AplmtThreadWorkerPoolHdl AplmtThreadWorkerPool* /*-------------- INLINE PLATFORM IMPLEMENTATION ----------------------------*/ #include "aplmt/os/workers.h" /* For: inline implementation */ /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method is used to initialize the worker pool. This method must be called before any other method in this interface. The parameter 'defaultPriority' is the priority that is assigned to all Thread Workers in the pool. NOTES: o The caller is responsible for supply the memory for the worker pool. Prototype: void Aplmt_initThreadWorkerPool( AplmtThreadWorkerPool* workerPoolToInit ); */ #define Aplmt_initThreadWorkerPool _Aplmt_initThreadWorkerPool /** This method is used to add a Thread Worker to a Worker Pool. This method is the mechanism for populating the Worker Pool. This method should only be called by the creater/owner of the Worker Pool. On success this method returns 1 (true). If there is an error in creating the worker thread, then 0 (false) is returned. NOTES: o The caller is required to provide the memory for the Thread Worker's internal node structure. The funciton parameter 'memoryForWorkerStruct' MUST point to memory that the caller has allocated specifically for the worker being added. Each worker added must have its own instance of 'memoryForWorkerStruct'. Also, the scope of the memory is forever (i.e. never free/de-allocate it). o It is recommended that the 'workerPriority' parameter be same or a within predetermined set of priorities for ALL Thread Workers addded to a given worker pool. This is because is because there is no guaranty on order of 'allocation' with respect to requesting Thread Workers from a worker pool. Prototype AplBool Aplmt_addThreadWorker( AplmtThreadWorkerPoolHdl workerPool, const char* workerName, AplmtThreadPriority workerPriority, AplmtThreadWorker* memoryForWorkerStruct, AplmtThreadfacHdl threadFactoryToUse ); */ #define Aplmt_addThreadWorker _Aplmt_addThreadWorker /** This method can also be used to add a Thread Worker to a Worker Pool. The caller provides a pre-created APLMT thread for the Worker instead of letting the Worker Pool create the thread using a thread factory. While, this method is more flexible, CARE must be taken when the application creates the APLMT thread. The following rules apply for creating the raw thread. 1) The rawThread MUST be a APLMT thread. 2) You MUST use the helper function Aplmt_getThreadWorkerEntryFunc() to specify the entry function for the rawThread. 3) The rawThread's entry function argument MUST be a pointer to a previously allcoated AplmtThreadWorker struct. 4) The rawThread MUST be created in the APLMT_THREADSTATE_WAITING state. 5) You MUST pass the same pointer from rule 3 as the 'workerStructUsedWhenThreadWasCreated' parameter to this method. NOTES: o The application is responsible for providing the AplmtThreadWorker memory for each Thread Worker. The allocate memory must have the same scope/lifetime of the Thread Workers. o It is recommended that the 'workerPriority' parameter be same or a within predetermined set of priorities for ALL Thread Workers addded to a given worker pool. This is because is because there is no guaranty on order of 'allocation' with respect to requesting Thread Workers from a worker pool. o Exception to the previous guideline. It is possible to use Thread Worker Pools as an alternate to Thread Factories given the following restrictions: - For ALL thread workers in the pool, the workers either never finish their dispatched work or self terminate when their assigned work is done (i.e. once a thread worker is removed from the pool's free list, it is never returned to the pool). - The order Thread Workers are added to the worker pool is the order they are 'requested' (i.e. the worker pool uses a FIFO queue for its free list). Prototype void Aplmt_addThreadWorkerRawThread( AplmtThreadWorkerPoolHdl workerPool AplmtThreadHdl rawThread, AplmtThreadWorkerHdl workerStructUsedWhenThreadWasCreated ); */ #define Aplmt_addThreadWorkerRawThread _Aplmt_addThreadWorkerRawThread /** This method is a helper function to Aplmt_addThreadWorkerRawThread(), it returns the thread entry function for a Thread Worker. Prototype: AplmtThreadEntry Aplmt_getThreadWorkerEntryFunc(void); */ #define Aplmt_getThreadWorkerEntryFunc _Aplmt_getThreadWorkerEntryFunc /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method returns an available Thread Worker that is ready for work. If no worker is available, then 0 is returned. Prototype: AplmtThreadWorkerHdl Aplmt_requestThreadWorker( AplmtThreadWorkerPoolHdl workerPool ); */ #define Aplmt_requestThreadWorker _Aplmt_requestThreadWorker /** This method is used to dispatch a chunk of work to a Thread Worker. This call will wake-up the Thread Worker to perform the specified work. The Thread Worker performs the following actions when woken up. 1) If the 'preWork' function is not 0, then execute it. The parameter 'preArg' is passed to 'preWork' 2) Executes the 'work' funciton. The parameter 'workArg' is passed to 'work'. 3) If the 'postWork' function is not 0, then execute it. The parameter 'postArg' is passed to 'postWork' 4) Puts itself back into its Worker Pool free list, and then goes to sleep to wait for the next dispatch request. NOTES: o This method returns the actual APLMT thread handle of the dispatched Thread Worker. o All worker functions (preWork,work, postWork) run in the context of the worker thread - not the caller's thread. o The function parameters preWork, preArg, workArg, postWork, and postArg can be be NULL/0 if not needed. Prototype: AplmtThreadHdl Aplmt_dispatchThreadWorker( AplmtThreadWorkerHdl worker, AplmtUnitOfWorkFunc preWork, void* preArg, AplmtUnitOfWorkFunc work, void* workArg, AplmtUnitOfWorkFunc postWork, void* postArg ); */ #define Aplmt_dispatchThreadWorker _Aplmt_dispatchThreadWorker /** This method returns the APLMT thread handle of the specified Thread Worker. Prototype: AplmtThreadHdl _Aplmt_getThreadWorkerThreadHdl( AplmtThreadWorkerHdl worker ); */ #define Aplmt_getThreadWorkerThreadHdl _Aplmt_getThreadWorkerThreadHdl /** This method is used to terminate a Thread Worker. By default, Thread Workers live forever. This method must be enabled at compile time using the switch USE_APLMT_TWRKPOOL_ENABLE_WORKERS_TERMINATE. The application terminates a Thread Worker by having one of the unit-of- work functions call this method. Once the Thread Worker has completed all of its worked assigned by the dispatch function, the Thread Worker will be terminate (i.e. the thread itself terminates). NOTES: o This method can ONLY be called from the thread context of the Thread Worker! o The function parameter 'myself' MUST be a handle to the Thread Worker that is currently executing. Prototype: void Aplmt_terminateThreadWorkerAtEndOfWork(AplmtThreadWorkerHdl myself); */ #define Aplmt_terminateThreadWorkerAtEndOfWork _Aplmt_terminateThreadWorkerAtEndOfWork #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------*/ #endif /* end _aplmt_os_workersapi_h_ */