289 lignes
11 KiB
C
289 lignes
11 KiB
C
#ifndef cmThread_h
|
|
#define cmThread_h
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef cmHandle_t cmThreadH_t;
|
|
typedef unsigned cmThRC_t;
|
|
|
|
enum
|
|
{
|
|
kOkThRC = cmOkRC, // 0
|
|
kCreateFailThRC, // 1
|
|
kDestroyFailThRC, // 2
|
|
kTimeOutThRC, // 3
|
|
kInvalidHandleThRC, // 4
|
|
kLockFailThRC, // 5
|
|
kUnlockFailThRC, // 6
|
|
kCVarWaitFailThRC, // 7
|
|
kCVarSignalFailThRC, // 8
|
|
kBufFullThRC, // 9
|
|
kBufEmptyThRC, // 10
|
|
kBufTooSmallThRC // 11
|
|
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
kNotInitThId,
|
|
kPausedThId,
|
|
kRunningThId,
|
|
kExitedThId
|
|
} cmThStateId_t;
|
|
|
|
|
|
// Return 'false' to indicate that the thread should terminate
|
|
// otherwise return 'true'
|
|
typedef bool (*cmThreadFunc_t)(void* param);
|
|
|
|
extern cmThreadH_t cmThreadNullHandle;
|
|
|
|
// Create a thread. The thread is automatically set to the 'paused' state.
|
|
cmThRC_t cmThreadCreate( cmThreadH_t* hPtr, cmThreadFunc_t cmThreadFuncPtr, void* funcParam, cmRpt_t* rpt );
|
|
|
|
// Release the resources associated with a thread previously created with cmThreadCreate().
|
|
cmThRC_t cmThreadDestroy( cmThreadH_t* hPtr );
|
|
|
|
enum
|
|
{
|
|
kPauseThFl = 0x01, // set to pause, clear to unpause
|
|
kWaitThFl = 0x02 // set to wait for thread to pause/unpause prior to returning.
|
|
};
|
|
|
|
// Pause or unpause a thread. Set kWaitThFl to wait for the thread to be
|
|
// paused or unpaused prior to returning.
|
|
cmThRC_t cmThreadPause( cmThreadH_t h, unsigned cmdFlags );
|
|
|
|
// Return the current thread state.
|
|
cmThStateId_t cmThreadState( cmThreadH_t h );
|
|
bool cmThreadIsValid( cmThreadH_t h);
|
|
|
|
// The Pause time out gives the period in microseconds which the thread will
|
|
// sleep while it is paused. In other words the thread will wake up
|
|
// every 'pause time out micro-seconds' to check to see if it has been
|
|
// requested to leave the paused state. Default:50000.
|
|
unsigned cmThreadPauseTimeOutMicros( cmThreadH_t h );
|
|
void cmThreadSetPauseTimeOutMicros( cmThreadH_t h, unsigned usecs );
|
|
|
|
// The wait time out gives the length of time the thread should expect to
|
|
// wait in order change states. This value should always be greater than
|
|
// or equal to the pause time out and the expected length of time the
|
|
// client callback function will run.
|
|
// This timeout comes into play in two situations:
|
|
// 1) This is the maximum length of time that cmThreadPause() will wait for
|
|
// the thread to enter/leave the pause state when the kWaitThFl has been set.
|
|
// If the thread does not enter/leave the pause state in this amount of time
|
|
// then cmThreadPause() returns the error code kTimeOutThRC.
|
|
// 2) This is the maximum length of time the cmThreadDestroy() wll wait for
|
|
// the thread to enter the 'exited' state after being requested to destroy
|
|
// itself. If this time period expires then cmThreadDestroy() returns
|
|
// kTimeOutThRC.
|
|
// Default:1000000.
|
|
unsigned cmThreadWaitTimeOutMicros( cmThreadH_t h );
|
|
void cmThreadSetWaitTimeOutMicros( cmThreadH_t h, unsigned usecs );
|
|
|
|
void cmThreadTest( cmRpt_t* rpt );
|
|
|
|
|
|
typedef struct
|
|
{
|
|
void* h;
|
|
} cmThreadMutexH_t;
|
|
|
|
extern cmThreadMutexH_t kCmThreadMutexNULL;
|
|
|
|
cmThRC_t cmThreadMutexCreate( cmThreadMutexH_t* hPtr, cmRpt_t* rpt );
|
|
cmThRC_t cmThreadMutexDestroy( cmThreadMutexH_t* hPtr );
|
|
cmThRC_t cmThreadMutexTryLock( cmThreadMutexH_t h, bool* lockFlPtr );
|
|
cmThRC_t cmThreadMutexLock( cmThreadMutexH_t h );
|
|
cmThRC_t cmThreadMutexUnlock( cmThreadMutexH_t h );
|
|
bool cmThreadMutexIsValid( cmThreadMutexH_t h );
|
|
|
|
// Set 'lockFl' if the function should lock the mutex prior to waiting.
|
|
// If 'lockFl' is false then the function assumes the mutex is already locked
|
|
// and directly waits. If 'lockFl' is set and the mutex is not already locked
|
|
// then the result is undefined.
|
|
cmThRC_t cmThreadMutexWaitOnCondVar( cmThreadMutexH_t h, bool lockFl );
|
|
cmThRC_t cmThreadMutexSignalCondVar( cmThreadMutexH_t h );
|
|
|
|
|
|
|
|
// cmThread safe message queue.
|
|
//
|
|
// This object is intended as a way to serialize one-way
|
|
// communication between multiple sender threads and one
|
|
// receiver thread. The object is implemented as
|
|
// a double buffer. One buffer acts as
|
|
// an input queue the the other buffer acts as an
|
|
// output queue. When the output queue is empty the buffers
|
|
// are swapped. Any pending messages in the input queue
|
|
// then become available to the receiver in the output queue.
|
|
//
|
|
// An internal mutex prevents the queue logic from becoming
|
|
// corrupted. The mutex is locked during the entire enqueue
|
|
// operation. The enqueue operation may therefore block its
|
|
// thread while waiting for mutex access. The dequeue operation
|
|
// only locks the mutex when the current output buffer is
|
|
// empty, the input buffer contains messages, and the mutex
|
|
// is not already locked. The mutex only remains locked for the
|
|
// period of time necessary to switch the input and output
|
|
// buffer pointers. The mutex is not locked during the actual
|
|
// dequeue copy or transmit.
|
|
//
|
|
// Given this logic the dequeue thread should never
|
|
// block because it only locks the mutex when it is not already
|
|
// locked. The enqueue thread will only block when it happens to collide
|
|
// with the dequeue buffer switch operation or an enqueue operation
|
|
// from another thread. If it happens that there is only a single
|
|
// sender thread then the sender will virtually never block because
|
|
// the dequeue lock is only maintained for a very short period of time.
|
|
//
|
|
|
|
typedef cmHandle_t cmTsQueueH_t;
|
|
|
|
extern cmTsQueueH_t cmTsQueueNullHandle;
|
|
|
|
typedef cmRC_t (*cmTsQueueCb_t)(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr );
|
|
|
|
// Set 'cbFunc' to NULL if the dequeue callback option will not be used.
|
|
cmThRC_t cmTsQueueCreate( cmTsQueueH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
|
|
cmThRC_t cmTsQueueDestroy( cmTsQueueH_t* hPtr );
|
|
|
|
// Set or clear the dequeue callback option after the queue was created.
|
|
cmThRC_t cmTsQueueSetCallback( cmTsQueueH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
|
|
|
|
// Copy a msg into the queue. This function return kBufFullThRC if the buffer is full.
|
|
// This interface allows the message to be formed from a concatenation of 'arrayCnt' segments.
|
|
cmThRC_t cmTsQueueEnqueueSegMsg( cmTsQueueH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
|
|
|
|
// Copy a msg onto the queue. This function is written in terms of cmTsQueueEnqueueSegMsg().
|
|
cmThRC_t cmTsQueueEnqueueMsg( cmTsQueueH_t h, const void* dataPtr, unsigned byteCnt );
|
|
|
|
// Prepend 'id' to the bytes contained in 'dataPtr[byteCnt]' and enqueue the resulting msg.
|
|
// This function is written in terms of cmTesQueueEnqueueSegMsg().
|
|
cmThRC_t cmTsQueueEnqueueIdMsg( cmTsQueueH_t h, unsigned id, const void* dataPtr, unsigned byteCnt );
|
|
|
|
// Total size of the queue buffer.
|
|
unsigned cmTsQueueAllocByteCount( cmTsQueueH_t h );
|
|
|
|
// Bytes available to enqueue the next message.
|
|
unsigned cmTsQueueAvailByteCount( cmTsQueueH_t h );
|
|
|
|
// Remove one msg from the queue.
|
|
// If 'dataPtr' is not NULL the msg is copied into the buffer it points to.
|
|
// If 'cbFunc' in the earlier call to cmTsQueueCreate() was not NULL then
|
|
// the msg is transmitted via the callback.
|
|
// This function should only be called from the deque thread.
|
|
cmThRC_t cmTsQueueDequeueMsg( cmTsQueueH_t h, void* dataPtr, unsigned byteCnt );
|
|
|
|
// thQueueMsgWaiting() returns true if there is a msg available
|
|
// to dequeue. This function should only be called from the
|
|
// deque thread.
|
|
bool cmTsQueueMsgWaiting( cmTsQueueH_t h );
|
|
|
|
// Return the size in bytes of the next msg to dequeue or zero
|
|
// if no msgs are waiting. The function should only be called from the
|
|
// deque thread.
|
|
unsigned cmTsQueueDequeueMsgByteCount( cmTsQueueH_t h );
|
|
|
|
bool cmTsQueueIsValid( cmTsQueueH_t h);
|
|
|
|
|
|
// Single producer / Single consumer thread-safe queue.
|
|
// These functions have identical semantics and return values
|
|
// to the same named cmTsQueueXXXX() calls above.
|
|
|
|
typedef cmHandle_t cmTs1p1cH_t;
|
|
|
|
extern cmTs1p1cH_t cmTs1p1cNullHandle;
|
|
|
|
cmThRC_t cmTs1p1cCreate( cmTs1p1cH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
|
|
|
|
cmThRC_t cmTs1p1cDestroy( cmTs1p1cH_t* hPtr );
|
|
|
|
cmThRC_t cmTs1p1cSetCallback( cmTs1p1cH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
|
|
|
|
cmThRC_t cmTs1p1cEnqueueSegMsg( cmTs1p1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
|
|
|
|
cmThRC_t cmTs1p1cEnqueueMsg( cmTs1p1cH_t h, const void* dataPtr, unsigned byteCnt );
|
|
|
|
unsigned cmTs1p1cAllocByteCount( cmTs1p1cH_t h );
|
|
|
|
unsigned cmTs1p1cAvailByteCount( cmTs1p1cH_t h );
|
|
|
|
cmThRC_t cmTs1p1cDequeueMsg( cmTs1p1cH_t h, void* dataPtr, unsigned byteCnt );
|
|
|
|
bool cmTs1p1cMsgWaiting( cmTs1p1cH_t h );
|
|
|
|
unsigned cmTs1p1cDequeueMsgByteCount( cmTs1p1cH_t h );
|
|
|
|
bool cmTs1p1cIsValid( cmTs1p1cH_t h );
|
|
|
|
|
|
// Thread safe compare-and-swap (actualy compare-and-test).
|
|
// Returns true if the *addr==new when the function returns
|
|
// otherwise returns false.
|
|
bool cmThIntCAS( int* addr, int old, int neww );
|
|
bool cmThUIntCAS( unsigned* addr, unsigned old, unsigned neww );
|
|
bool cmThFloatCAS( float* addr, float old, float neww );
|
|
|
|
// Note: voidPtrPtr is must really be a pointer to a pointer.
|
|
bool cmThPtrCAS( void* voidPtrPtr, void* old, void* neww );
|
|
|
|
// Thread safe increment and decrement implemented in terms of
|
|
// cmThXXXCAS().
|
|
void cmThIntIncr( int* addr, int incr );
|
|
void cmThUIntIncr( unsigned* addr, unsigned incr );
|
|
void cmThFloatIncr(float* addr, float incr );
|
|
void cmThIntDecr( int* addr, int decr );
|
|
void cmThUIntDecr( unsigned* addr, unsigned decr );
|
|
void cmThFloatDecr(float* addr, float decr );
|
|
|
|
// Multiple producer / Single consumer thread-safe queue.
|
|
// These functions have identical semantics and return values
|
|
// to the same named cmTsQueueXXXX() calls above.
|
|
|
|
typedef cmHandle_t cmTsMp1cH_t;
|
|
|
|
extern cmTsMp1cH_t cmTsMp1cNullHandle;
|
|
|
|
cmThRC_t cmTsMp1cCreate( cmTsMp1cH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
|
|
cmThRC_t cmTsMp1cDestroy( cmTsMp1cH_t* hPtr );
|
|
|
|
void cmTsMp1cSetCbFunc( cmTsMp1cH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
|
|
cmTsQueueCb_t cmTsMp1cCbFunc( cmTsMp1cH_t h );
|
|
void* cmTsMp1cCbArg( cmTsMp1cH_t h );
|
|
|
|
cmThRC_t cmTsMp1cEnqueueSegMsg( cmTsMp1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
|
|
|
|
cmThRC_t cmTsMp1cEnqueueMsg( cmTsMp1cH_t h, const void* dataPtr, unsigned byteCnt );
|
|
|
|
unsigned cmTsMp1cAllocByteCount( cmTsMp1cH_t h );
|
|
|
|
unsigned cmTsMp1cAvailByteCount( cmTsMp1cH_t h );
|
|
|
|
cmThRC_t cmTsMp1cDequeueMsg( cmTsMp1cH_t h, void* dataPtr, unsigned byteCnt );
|
|
|
|
bool cmTsMp1cMsgWaiting( cmTsMp1cH_t h );
|
|
|
|
unsigned cmTsMp1cDequeueMsgByteCount( cmTsMp1cH_t h );
|
|
|
|
bool cmTsMp1cIsValid( cmTsMp1cH_t h );
|
|
|
|
|
|
// Sleep functions
|
|
void cmSleepUs( unsigned microseconds );
|
|
void cmSleepMs( unsigned milliseconds );
|
|
|
|
|
|
void cmTsQueueTest( cmRpt_t* rpt );
|
|
void cmTs1p1cTest( cmRpt_t* rpt );
|
|
void cmTsMp1cTest( cmRpt_t* rpt );
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|