libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmThread.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #ifndef cmThread_h
  2. #define cmThread_h
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. typedef cmHandle_t cmThreadH_t;
  7. typedef unsigned cmThRC_t;
  8. enum
  9. {
  10. kOkThRC = cmOkRC, // 0
  11. kCreateFailThRC, // 1
  12. kDestroyFailThRC, // 2
  13. kTimeOutThRC, // 3
  14. kInvalidHandleThRC, // 4
  15. kLockFailThRC, // 5
  16. kUnlockFailThRC, // 6
  17. kCVarWaitFailThRC, // 7
  18. kCVarSignalFailThRC, // 8
  19. kBufFullThRC, // 9
  20. kBufEmptyThRC, // 10
  21. kBufTooSmallThRC // 11
  22. };
  23. typedef enum
  24. {
  25. kNotInitThId,
  26. kPausedThId,
  27. kRunningThId,
  28. kExitedThId
  29. } cmThStateId_t;
  30. // Return 'false' to indicate that the thread should terminate
  31. // otherwise return 'true'
  32. typedef bool (*cmThreadFunc_t)(void* param);
  33. extern cmThreadH_t cmThreadNullHandle;
  34. // Create a thread. The thread is automatically set to the 'paused' state.
  35. cmThRC_t cmThreadCreate( cmThreadH_t* hPtr, cmThreadFunc_t cmThreadFuncPtr, void* funcParam, cmRpt_t* rpt );
  36. // Release the resources associated with a thread previously created with cmThreadCreate().
  37. cmThRC_t cmThreadDestroy( cmThreadH_t* hPtr );
  38. enum
  39. {
  40. kPauseThFl = 0x01, // set to pause, clear to unpause
  41. kWaitThFl = 0x02 // set to wait for thread to pause/unpause prior to returning.
  42. };
  43. // Pause or unpause a thread. Set kWaitThFl to wait for the thread to be
  44. // paused or unpaused prior to returning.
  45. cmThRC_t cmThreadPause( cmThreadH_t h, unsigned cmdFlags );
  46. // Return the current thread state.
  47. cmThStateId_t cmThreadState( cmThreadH_t h );
  48. bool cmThreadIsValid( cmThreadH_t h);
  49. // The Pause time out gives the period in microseconds which the thread will
  50. // sleep while it is paused. In other words the thread will wake up
  51. // every 'pause time out micro-seconds' to check to see if it has been
  52. // requested to leave the paused state. Default:50000.
  53. unsigned cmThreadPauseTimeOutMicros( cmThreadH_t h );
  54. void cmThreadSetPauseTimeOutMicros( cmThreadH_t h, unsigned usecs );
  55. // The wait time out gives the length of time the thread should expect to
  56. // wait in order change states. This value should always be greater than
  57. // or equal to the pause time out and the expected length of time the
  58. // client callback function will run.
  59. // This timeout comes into play in two situations:
  60. // 1) This is the maximum length of time that cmThreadPause() will wait for
  61. // the thread to enter/leave the pause state when the kWaitThFl has been set.
  62. // If the thread does not enter/leave the pause state in this amount of time
  63. // then cmThreadPause() returns the error code kTimeOutThRC.
  64. // 2) This is the maximum length of time the cmThreadDestroy() wll wait for
  65. // the thread to enter the 'exited' state after being requested to destroy
  66. // itself. If this time period expires then cmThreadDestroy() returns
  67. // kTimeOutThRC.
  68. // Default:1000000.
  69. unsigned cmThreadWaitTimeOutMicros( cmThreadH_t h );
  70. void cmThreadSetWaitTimeOutMicros( cmThreadH_t h, unsigned usecs );
  71. void cmThreadTest( cmRpt_t* rpt );
  72. typedef struct
  73. {
  74. void* h;
  75. } cmThreadMutexH_t;
  76. extern cmThreadMutexH_t kCmThreadMutexNULL;
  77. cmThRC_t cmThreadMutexCreate( cmThreadMutexH_t* hPtr, cmRpt_t* rpt );
  78. cmThRC_t cmThreadMutexDestroy( cmThreadMutexH_t* hPtr );
  79. cmThRC_t cmThreadMutexTryLock( cmThreadMutexH_t h, bool* lockFlPtr );
  80. cmThRC_t cmThreadMutexLock( cmThreadMutexH_t h );
  81. cmThRC_t cmThreadMutexUnlock( cmThreadMutexH_t h );
  82. bool cmThreadMutexIsValid( cmThreadMutexH_t h );
  83. // Set 'lockFl' if the function should lock the mutex prior to waiting.
  84. // If 'lockFl' is false then the function assumes the mutex is already locked
  85. // and directly waits. If 'lockFl' is set and the mutex is not already locked
  86. // then the result is undefined.
  87. cmThRC_t cmThreadMutexWaitOnCondVar( cmThreadMutexH_t h, bool lockFl );
  88. cmThRC_t cmThreadMutexSignalCondVar( cmThreadMutexH_t h );
  89. // cmThread safe message queue.
  90. //
  91. // This object is intended as a way to serialize one-way
  92. // communication between multiple sender threads and one
  93. // receiver thread. The object is implemented as
  94. // a double buffer. One buffer acts as
  95. // an input queue the the other buffer acts as an
  96. // output queue. When the output queue is empty the buffers
  97. // are swapped. Any pending messages in the input queue
  98. // then become available to the receiver in the output queue.
  99. //
  100. // An internal mutex prevents the queue logic from becoming
  101. // corrupted. The mutex is locked during the entire enqueue
  102. // operation. The enqueue operation may therefore block its
  103. // thread while waiting for mutex access. The dequeue operation
  104. // only locks the mutex when the current output buffer is
  105. // empty, the input buffer contains messages, and the mutex
  106. // is not already locked. The mutex only remains locked for the
  107. // period of time necessary to switch the input and output
  108. // buffer pointers. The mutex is not locked during the actual
  109. // dequeue copy or transmit.
  110. //
  111. // Given this logic the dequeue thread should never
  112. // block because it only locks the mutex when it is not already
  113. // locked. The enqueue thread will only block when it happens to collide
  114. // with the dequeue buffer switch operation or an enqueue operation
  115. // from another thread. If it happens that there is only a single
  116. // sender thread then the sender will virtually never block because
  117. // the dequeue lock is only maintained for a very short period of time.
  118. //
  119. typedef cmHandle_t cmTsQueueH_t;
  120. extern cmTsQueueH_t cmTsQueueNullHandle;
  121. typedef cmRC_t (*cmTsQueueCb_t)(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr );
  122. // Set 'cbFunc' to NULL if the dequeue callback option will not be used.
  123. cmThRC_t cmTsQueueCreate( cmTsQueueH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
  124. cmThRC_t cmTsQueueDestroy( cmTsQueueH_t* hPtr );
  125. // Set or clear the dequeue callback option after the queue was created.
  126. cmThRC_t cmTsQueueSetCallback( cmTsQueueH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
  127. // Copy a msg into the queue. This function return kBufFullThRC if the buffer is full.
  128. // This interface allows the message to be formed from a concatenation of 'arrayCnt' segments.
  129. cmThRC_t cmTsQueueEnqueueSegMsg( cmTsQueueH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
  130. // Copy a msg onto the queue. This function is written in terms of cmTsQueueEnqueueSegMsg().
  131. cmThRC_t cmTsQueueEnqueueMsg( cmTsQueueH_t h, const void* dataPtr, unsigned byteCnt );
  132. // Prepend 'id' to the bytes contained in 'dataPtr[byteCnt]' and enqueue the resulting msg.
  133. // This function is written in terms of cmTesQueueEnqueueSegMsg().
  134. cmThRC_t cmTsQueueEnqueueIdMsg( cmTsQueueH_t h, unsigned id, const void* dataPtr, unsigned byteCnt );
  135. // Total size of the queue buffer.
  136. unsigned cmTsQueueAllocByteCount( cmTsQueueH_t h );
  137. // Bytes available to enqueue the next message.
  138. unsigned cmTsQueueAvailByteCount( cmTsQueueH_t h );
  139. // Remove one msg from the queue.
  140. // If 'dataPtr' is not NULL the msg is copied into the buffer it points to.
  141. // If 'cbFunc' in the earlier call to cmTsQueueCreate() was not NULL then
  142. // the msg is transmitted via the callback.
  143. // This function should only be called from the deque thread.
  144. cmThRC_t cmTsQueueDequeueMsg( cmTsQueueH_t h, void* dataPtr, unsigned byteCnt );
  145. // thQueueMsgWaiting() returns true if there is a msg available
  146. // to dequeue. This function should only be called from the
  147. // deque thread.
  148. bool cmTsQueueMsgWaiting( cmTsQueueH_t h );
  149. // Return the size in bytes of the next msg to dequeue or zero
  150. // if no msgs are waiting. The function should only be called from the
  151. // deque thread.
  152. unsigned cmTsQueueDequeueMsgByteCount( cmTsQueueH_t h );
  153. bool cmTsQueueIsValid( cmTsQueueH_t h);
  154. // Single producer / Single consumer thread-safe queue.
  155. // These functions have identical semantics and return values
  156. // to the same named cmTsQueueXXXX() calls above.
  157. typedef cmHandle_t cmTs1p1cH_t;
  158. extern cmTs1p1cH_t cmTs1p1cNullHandle;
  159. cmThRC_t cmTs1p1cCreate( cmTs1p1cH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
  160. cmThRC_t cmTs1p1cDestroy( cmTs1p1cH_t* hPtr );
  161. cmThRC_t cmTs1p1cEnqueueSegMsg( cmTs1p1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
  162. cmThRC_t cmTs1p1cEnqueueMsg( cmTs1p1cH_t h, const void* dataPtr, unsigned byteCnt );
  163. unsigned cmTs1p1cAllocByteCount( cmTs1p1cH_t h );
  164. unsigned cmTs1p1cAvailByteCount( cmTs1p1cH_t h );
  165. cmThRC_t cmTs1p1cDequeueMsg( cmTs1p1cH_t h, void* dataPtr, unsigned byteCnt );
  166. bool cmTs1p1cMsgWaiting( cmTs1p1cH_t h );
  167. unsigned cmTs1p1cDequeueMsgByteCount( cmTs1p1cH_t h );
  168. bool cmTs1p1cIsValid( cmTs1p1cH_t h );
  169. // Thread safe compare-and-swap (actualy compare-and-test).
  170. // Returns true if the *addr==new when the function returns
  171. // otherwise returns false.
  172. bool cmThIntCAS( int* addr, int old, int neww );
  173. bool cmThUIntCAS( unsigned* addr, unsigned old, unsigned neww );
  174. bool cmThFloatCAS( float* addr, float old, float neww );
  175. // Thread safe increment and decrement implemented in terms of
  176. // cmThXXXCAS().
  177. void cmThIntIncr( int* addr, int incr );
  178. void cmThUIntIncr( unsigned* addr, unsigned incr );
  179. void cmThFloatIncr(float* addr, float incr );
  180. void cmThIntDecr( int* addr, int decr );
  181. void cmThUIntDecr( unsigned* addr, unsigned decr );
  182. void cmThFloatDecr(float* addr, float decr );
  183. // Multiple producer / Single consumer thread-safe queue.
  184. // These functions have identical semantics and return values
  185. // to the same named cmTsQueueXXXX() calls above.
  186. typedef cmHandle_t cmTsMp1cH_t;
  187. extern cmTsMp1cH_t cmTsMp1cNullHandle;
  188. cmThRC_t cmTsMp1cCreate( cmTsMp1cH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
  189. cmThRC_t cmTsMp1cDestroy( cmTsMp1cH_t* hPtr );
  190. void cmTsMp1cSetCbFunc( cmTsMp1cH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
  191. cmTsQueueCb_t cmTsMp1cCbFunc( cmTsMp1cH_t h );
  192. void* cmTsMp1cCbArg( cmTsMp1cH_t h );
  193. cmThRC_t cmTsMp1cEnqueueSegMsg( cmTsMp1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
  194. cmThRC_t cmTsMp1cEnqueueMsg( cmTsMp1cH_t h, const void* dataPtr, unsigned byteCnt );
  195. unsigned cmTsMp1cAllocByteCount( cmTsMp1cH_t h );
  196. unsigned cmTsMp1cAvailByteCount( cmTsMp1cH_t h );
  197. cmThRC_t cmTsMp1cDequeueMsg( cmTsMp1cH_t h, void* dataPtr, unsigned byteCnt );
  198. bool cmTsMp1cMsgWaiting( cmTsMp1cH_t h );
  199. unsigned cmTsMp1cDequeueMsgByteCount( cmTsMp1cH_t h );
  200. bool cmTsMp1cIsValid( cmTsMp1cH_t h );
  201. void cmTsQueueTest( cmRpt_t* rpt );
  202. void cmTs1p1cTest( cmRpt_t* rpt );
  203. void cmTsMp1cTest( cmRpt_t* rpt );
  204. #ifdef __cplusplus
  205. }
  206. #endif
  207. #endif