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

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