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 12KB

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