threads.bmx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. Strict
  2. Rem
  3. bbdoc: System/Threads
  4. End Rem
  5. Module BRL.Threads
  6. ModuleInfo "License: zlib/libpng"
  7. ModuleInfo "Copyright: Blitz Research Ltd"
  8. ?Threaded
  9. Import "threads.c"
  10. Private
  11. Extern
  12. Function bbThreadAllocData()
  13. Function bbThreadSetData( index,data:Object )
  14. Function bbThreadGetData:Object( index )
  15. Function bbAtomicCAS( target Var,old_value,new_value )
  16. Function bbAtomicAdd( target Var,value )
  17. Function threads_CreateThread( entry:Object( data:Object ),data:Object )
  18. Function threads_DetachThread( thread )
  19. Function threads_WaitThread:Object( thread )
  20. Function threads_CreateMutex()
  21. Function threads_CloseMutex( mutex )
  22. Function threads_LockMutex( mutex )
  23. Function threads_TryLockMutex( mutex )
  24. Function threads_UnlockMutex( mutex )
  25. Function threads_CreateSemaphore( count )
  26. Function threads_CloseSemaphore( sema )
  27. Function threads_WaitSemaphore( sema )
  28. Function threads_PostSemaphore( sema )
  29. Function threads_CreateCond()
  30. Function threads_WaitCond( cond,mutex )
  31. Function threads_SignalCond( cond )
  32. Function threads_BroadcastCond( cond )
  33. Function threads_CloseCond( cond )
  34. End Extern
  35. Global _mainThread:TThread=New TThread
  36. Global _curThread:TThreadData=TThreadData.Create()
  37. _curThread.SetValue _mainThread
  38. Public
  39. Rem
  40. bbdoc: Thread type
  41. End Rem
  42. Type TThread
  43. Rem
  44. bbdoc: Detach this thread
  45. End Rem
  46. Method Detach()
  47. If Not _handle Return 'don't Assert, as Detach is a form of Close() which always works...
  48. threads_DetachThread _handle
  49. _handle=0
  50. End Method
  51. Rem
  52. bbdoc: Wait for this thread to finish
  53. returns: The object returned by the thread.
  54. End Rem
  55. Method Wait:Object()
  56. If Not _handle Return _result 'don't Assert, as Wait is a form of Close() which always works...
  57. threads_WaitThread _handle
  58. _handle=0
  59. Return _result
  60. End Method
  61. Rem
  62. bbdoc: Check if this thread is running
  63. End Rem
  64. Method Running()
  65. Return _running
  66. End Method
  67. Rem
  68. bbdoc: Create a new thread
  69. End Rem
  70. Function Create:TThread( entry:Object( data:Object),data:Object )
  71. Local thread:TThread=New TThread
  72. thread._entry=entry
  73. thread._data=data
  74. thread._running=True
  75. thread._handle=threads_CreateThread( _EntryStub,thread )
  76. Return thread
  77. End Function
  78. Rem
  79. bbdoc: Get main thread
  80. returns: A thread object representing the main application thread.
  81. End Rem
  82. Function Main:TThread()
  83. Return _mainThread
  84. End Function
  85. Rem
  86. bbdoc: Get current thread
  87. returns: A thread object representing the current thread.
  88. End Rem
  89. Function Current:TThread()
  90. Return TThread( _curThread.GetValue() )
  91. End Function
  92. Function _EntryStub:Object( data:Object )
  93. Local thread:TThread=TThread( data )
  94. _curThread.SetValue thread
  95. thread._result=thread._entry( thread._data )
  96. thread._running=False
  97. End Function
  98. Method Delete()
  99. If _handle threads_DetachThread _handle
  100. End Method
  101. Field _running
  102. Field _handle
  103. Field _result:Object
  104. Field _entry:Object( data:Object )
  105. Field _data:Object
  106. End Type
  107. Rem
  108. bbdoc: ThreadData type
  109. End Rem
  110. Type TThreadData
  111. Rem
  112. bbdoc: Set thread data value
  113. End Rem
  114. Method SetValue( value:Object )
  115. bbThreadSetData _handle,value
  116. End Method
  117. Rem
  118. bbdoc: Get thread data value
  119. End Rem
  120. Method GetValue:Object()
  121. Return bbThreadGetData( _handle )
  122. End Method
  123. Rem
  124. bbdoc: Create thread data
  125. End Rem
  126. Function Create:TThreadData()
  127. Local handle=bbThreadAllocData()
  128. If Not handle Return
  129. Local data:TThreadData=New TThreadData
  130. data._handle=handle
  131. Return data
  132. End Function
  133. Field _handle
  134. End Type
  135. Rem
  136. bbdoc: Mutex type
  137. End Rem
  138. Type TMutex
  139. Rem
  140. bbdoc: Close the mutex
  141. End Rem
  142. Method Close()
  143. If Not _handle Return
  144. threads_CloseMutex _handle
  145. _handle=0
  146. End Method
  147. Rem
  148. bbdoc: Lock the mutex
  149. End Rem
  150. Method Lock()
  151. Assert _handle
  152. threads_LockMutex _handle
  153. End Method
  154. Rem
  155. bbdoc: Try to lock the mutex
  156. returns: #True if mutex was successfully locked; #False if mutex was already locked by another thread.
  157. End Rem
  158. Method TryLock()
  159. Assert _handle
  160. Return threads_TryLockMutex( _handle )
  161. End Method
  162. Rem
  163. bbdoc: Unlock the mutex
  164. End Rem
  165. Method Unlock()
  166. Assert _handle
  167. threads_UnlockMutex _handle
  168. End Method
  169. Rem
  170. bbdoc: Create a new mutex
  171. End Rem
  172. Function Create:TMutex()
  173. Local handle=threads_CreateMutex()
  174. If Not handle Return
  175. Local mutex:TMutex=New TMutex
  176. mutex._handle=handle
  177. Return mutex
  178. End Function
  179. Method Delete()
  180. If _handle threads_CloseMutex _handle
  181. End Method
  182. Field _handle
  183. End Type
  184. Rem
  185. bbdoc: Semaphore type
  186. End Rem
  187. Type TSemaphore
  188. Rem
  189. bbdoc: Close the semaphore
  190. End Rem
  191. Method Close()
  192. If Not _handle Return
  193. threads_CloseSemaphore _handle
  194. _handle=0
  195. End Method
  196. Rem
  197. bbdoc: Wait for the semaphore
  198. End Rem
  199. Method Wait()
  200. Assert _handle
  201. threads_WaitSemaphore _handle
  202. End Method
  203. Rem
  204. bbdoc: Post the semaphore
  205. End Rem
  206. Method Post()
  207. Assert _handle
  208. threads_PostSemaphore _handle
  209. End Method
  210. Rem
  211. bbdoc: Create a new semaphore
  212. End Rem
  213. Function Create:TSemaphore( count )
  214. Local handle=threads_CreateSemaphore( count )
  215. If Not handle Return
  216. Local semaphore:TSemaphore=New TSemaphore
  217. semaphore._handle=handle
  218. Return semaphore
  219. End Function
  220. Method Delete()
  221. If _handle threads_CloseSemaphore _handle
  222. End Method
  223. Field _handle
  224. End Type
  225. Rem
  226. bbdoc: CondVar type
  227. End Rem
  228. Type TCondVar
  229. Rem
  230. bbdoc: Close the condvar
  231. End Rem
  232. Method Close()
  233. If Not _handle Return
  234. threads_CloseCond _handle
  235. _handle=0
  236. End Method
  237. Rem
  238. bbdoc: Wait for the condvar
  239. End Rem
  240. Method Wait( mutex:TMutex )
  241. Assert _handle
  242. threads_WaitCond _handle,mutex._handle
  243. End Method
  244. Rem
  245. bbdoc: Signal the condvar
  246. End Rem
  247. Method Signal()
  248. Assert _handle
  249. threads_SignalCond _handle
  250. End Method
  251. Rem
  252. bbdoc: Broadcast the condvar
  253. End Rem
  254. Method Broadcast()
  255. Assert _handle
  256. threads_BroadcastCond _handle
  257. End Method
  258. Rem
  259. bbdoc: Create a new condvar
  260. End Rem
  261. Function Create:TCondVar()
  262. Local handle=threads_CreateCond()
  263. If Not handle Return
  264. Local condvar:TCondVar=New TCondVar
  265. condvar._handle=handle
  266. Return condvar
  267. End Function
  268. Method Delete()
  269. If _handle threads_CloseCond _handle
  270. End Method
  271. Field _handle
  272. End Type
  273. Rem
  274. bbdoc: Create a thread
  275. returns: A new thread object.
  276. about:
  277. Creates a thread and returns a thread object.
  278. The value returned by the thread @entry routine can be later retrieved using #WaitThread.
  279. To 'close' a thread, call either #DetachThread or #WaitThread. This isn't strictly
  280. necessary as the thread will eventually be closed when it is garbage collected, however, it
  281. may be a good idea if you are creating many threads very often, as some operating systems have
  282. a limit on the number of threads that can be allocated at once.
  283. End Rem
  284. Function CreateThread:TThread( entry:Object( data:Object ),data:Object )
  285. Return TThread.Create( entry,data )
  286. End Function
  287. Rem
  288. bbdoc: Get main thread
  289. returns: A thread object representing the main application thread.
  290. End Rem
  291. Function MainThread:TThread()
  292. Return _mainThread
  293. End Function
  294. Rem
  295. bbdoc: Get current thread
  296. returns: A thread object representing the current thread.
  297. End Rem
  298. Function CurrentThread:TThread()
  299. Return TThread( _curThread.GetValue() )
  300. End Function
  301. Rem
  302. bbdoc: Detach a thread
  303. about:
  304. #DetachThread closes a thread's handle, but does not halt or otherwise affect the target thread.
  305. Once one a thread has been detached, it wil no longer be possible to use #WaitThread to get its return value.
  306. This allows the thread to run without your program having to continually check whether it has completedin order to close it.
  307. End Rem
  308. Function DetachThread( thread:TThread )
  309. Return thread.Detach()
  310. End Function
  311. Rem
  312. bbdoc: Wait for a thread to finish
  313. returns: The object returned by the thread entry routine.
  314. about:
  315. #WaitThread causes the calling thread to block until the target thread has completed execution.
  316. If the target thread has already completed execution, #WaitThread returns immediately.
  317. The returned object is the object returned by the thread's entry routine, as passed to #CreateThread.
  318. End Rem
  319. Function WaitThread:Object( thread:TThread )
  320. Return thread.Wait()
  321. End Function
  322. Rem
  323. bbdoc: Check if a thread is running
  324. returns: #True if @thread is still running, otherwise #False.
  325. End Rem
  326. Function ThreadRunning( thread:TThread )
  327. Return thread.Running()
  328. End Function
  329. Rem
  330. bbdoc: Create thread data
  331. returns: A new thread data object.
  332. End Rem
  333. Function CreateThreadData:TThreadData()
  334. Return TThreadData.Create()
  335. End Function
  336. Rem
  337. bbdoc: Set thread data value
  338. End Rem
  339. Function SetThreadDataValue( data:TThreadData,value:Object )
  340. data.SetValue value
  341. End Function
  342. Rem
  343. bbdoc: Get thread data value
  344. End Rem
  345. Function GetThreadDataValue:Object( data:TThreadData )
  346. Return data.Getvalue()
  347. End Function
  348. Rem
  349. bbdoc: Create a mutex
  350. returns: A new mutex object
  351. End Rem
  352. Function CreateMutex:TMutex()
  353. Return TMutex.Create()
  354. End Function
  355. Rem
  356. bbdoc: Close a mutex
  357. End Rem
  358. Function CloseMutex( mutex:TMutex )
  359. mutex.Close
  360. End Function
  361. Rem
  362. bbdoc: Lock a mutex
  363. End Rem
  364. Function LockMutex( mutex:TMutex )
  365. mutex.Lock
  366. End Function
  367. Rem
  368. bbdoc: Try to lock a mutex
  369. returns: #True if @mutex was successfully locked; #False if @mutex was already locked by another thread.
  370. End Rem
  371. Function TryLockMutex( mutex:TMutex )
  372. Return mutex.TryLock()
  373. End Function
  374. Rem
  375. bbdoc: Unlock a mutex
  376. End Rem
  377. Function UnlockMutex( mutex:TMutex )
  378. mutex.Unlock
  379. End Function
  380. Rem
  381. bbdoc: Create a semaphore
  382. returns: A new semaphore object
  383. End Rem
  384. Function CreateSemaphore:TSemaphore( count )
  385. Return TSemaphore.Create( count )
  386. End Function
  387. Rem
  388. bbdoc: Close a semaphore
  389. End Rem
  390. Function CloseSemaphore( semaphore:TSemaphore )
  391. semaphore.Close
  392. End Function
  393. Rem
  394. bbdoc: Wait for a semaphore
  395. End Rem
  396. Function WaitSemaphore( semaphore:TSemaphore )
  397. semaphore.Wait
  398. End Function
  399. Rem
  400. bbdoc: Post a semaphore
  401. End Rem
  402. Function PostSemaphore( semaphore:TSemaphore )
  403. semaphore.Post
  404. End Function
  405. Rem
  406. bbdoc: Create a condvar
  407. returns: A new condvar object
  408. End Rem
  409. Function CreateCondVar:TCondVar()
  410. Return TCondVar.Create()
  411. End Function
  412. Rem
  413. bbdoc: Close a condvar
  414. End Rem
  415. Function CloseCondVar( condvar:TCondVar )
  416. condvar.Close
  417. End Function
  418. Rem
  419. bbdoc: Wait for a condvar
  420. End Rem
  421. Function WaitCondVar( condvar:TCondVar,mutex:TMutex )
  422. condvar.Wait mutex
  423. End Function
  424. Rem
  425. bbdoc: Signal a condvar
  426. End Rem
  427. Function SignalCondVar( condvar:TCondVar )
  428. condvar.Signal
  429. End Function
  430. Rem
  431. bbdoc: Broadcast a condvar
  432. End Rem
  433. Function BroadcastCondVar( condvar:TCondVar )
  434. condvar.Broadcast
  435. End Function
  436. Rem
  437. bbdoc: Compare and swap
  438. returns: @True if target was updated
  439. about:
  440. Atomically replace @target with @new_value if @target equals @old_value.
  441. End Rem
  442. Function CompareAndSwap( target Var,oldValue,newValue )
  443. Return bbAtomicCAS( target,oldValue,newValue )
  444. End Function
  445. Rem
  446. bbdoc: Atomic add
  447. returns: Previuous value of target
  448. about:
  449. Atomically add @value to @target.
  450. End Rem
  451. Function AtomicAdd( target Var,value )
  452. Return bbAtomicAdd( target,value )
  453. End Function
  454. Rem
  455. bbdoc: Atomically swap values
  456. returns: The old value of @target
  457. End Rem
  458. Function AtomicSwap( target Var,value )
  459. Repeat
  460. Local oldval=target
  461. If CompareAndSwap( target,oldval,value ) Return oldval
  462. Forever
  463. End Function
  464. ?