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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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 cmTs1p1cSetCallback( cmTs1p1cH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
  162. cmThRC_t cmTs1p1cEnqueueSegMsg( cmTs1p1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
  163. cmThRC_t cmTs1p1cEnqueueMsg( cmTs1p1cH_t h, const void* dataPtr, unsigned byteCnt );
  164. unsigned cmTs1p1cAllocByteCount( cmTs1p1cH_t h );
  165. unsigned cmTs1p1cAvailByteCount( cmTs1p1cH_t h );
  166. cmThRC_t cmTs1p1cDequeueMsg( cmTs1p1cH_t h, void* dataPtr, unsigned byteCnt );
  167. bool cmTs1p1cMsgWaiting( cmTs1p1cH_t h );
  168. unsigned cmTs1p1cDequeueMsgByteCount( cmTs1p1cH_t h );
  169. bool cmTs1p1cIsValid( cmTs1p1cH_t h );
  170. // Thread safe compare-and-swap (actualy compare-and-test).
  171. // Returns true if the *addr==new when the function returns
  172. // otherwise returns false.
  173. bool cmThIntCAS( int* addr, int old, int neww );
  174. bool cmThUIntCAS( unsigned* addr, unsigned old, unsigned neww );
  175. bool cmThFloatCAS( float* addr, float old, float neww );
  176. // Note: voidPtrPtr is must really be a pointer to a pointer.
  177. bool cmThPtrCAS( void* voidPtrPtr, void* old, void* neww );
  178. // Thread safe increment and decrement implemented in terms of
  179. // cmThXXXCAS().
  180. void cmThIntIncr( int* addr, int incr );
  181. void cmThUIntIncr( unsigned* addr, unsigned incr );
  182. void cmThFloatIncr(float* addr, float incr );
  183. void cmThIntDecr( int* addr, int decr );
  184. void cmThUIntDecr( unsigned* addr, unsigned decr );
  185. void cmThFloatDecr(float* addr, float decr );
  186. // Multiple producer / Single consumer thread-safe queue.
  187. // These functions have identical semantics and return values
  188. // to the same named cmTsQueueXXXX() calls above.
  189. typedef cmHandle_t cmTsMp1cH_t;
  190. extern cmTsMp1cH_t cmTsMp1cNullHandle;
  191. cmThRC_t cmTsMp1cCreate( cmTsMp1cH_t* hPtr, unsigned bufByteCnt, cmTsQueueCb_t cbFunc, void* cbArg, cmRpt_t* rpt );
  192. cmThRC_t cmTsMp1cDestroy( cmTsMp1cH_t* hPtr );
  193. void cmTsMp1cSetCbFunc( cmTsMp1cH_t h, cmTsQueueCb_t cbFunc, void* cbArg );
  194. cmTsQueueCb_t cmTsMp1cCbFunc( cmTsMp1cH_t h );
  195. void* cmTsMp1cCbArg( cmTsMp1cH_t h );
  196. cmThRC_t cmTsMp1cEnqueueSegMsg( cmTsMp1cH_t h, const void* msgPtrArray[], unsigned msgByteCntArray[], unsigned arrayCnt );
  197. cmThRC_t cmTsMp1cEnqueueMsg( cmTsMp1cH_t h, const void* dataPtr, unsigned byteCnt );
  198. unsigned cmTsMp1cAllocByteCount( cmTsMp1cH_t h );
  199. unsigned cmTsMp1cAvailByteCount( cmTsMp1cH_t h );
  200. cmThRC_t cmTsMp1cDequeueMsg( cmTsMp1cH_t h, void* dataPtr, unsigned byteCnt );
  201. bool cmTsMp1cMsgWaiting( cmTsMp1cH_t h );
  202. unsigned cmTsMp1cDequeueMsgByteCount( cmTsMp1cH_t h );
  203. bool cmTsMp1cIsValid( cmTsMp1cH_t h );
  204. // Sleep functions
  205. void cmSleepUs( unsigned microseconds );
  206. void cmSleepMs( unsigned milliseconds );
  207. void cmTsQueueTest( cmRpt_t* rpt );
  208. void cmTs1p1cTest( cmRpt_t* rpt );
  209. void cmTsMp1cTest( cmRpt_t* rpt );
  210. #ifdef __cplusplus
  211. }
  212. #endif
  213. #endif