libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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