primitives.odin 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package sync2
  2. import "core:time"
  3. current_thread_id :: proc "contextless" () -> int {
  4. return _current_thread_id()
  5. }
  6. // A Mutex is a mutual exclusion lock
  7. // The zero value for a Mutex is an unlocked mutex
  8. //
  9. // A Mutex must not be copied after first use
  10. Mutex :: struct {
  11. impl: _Mutex `This is a tag`,
  12. }
  13. // mutex_lock locks m
  14. mutex_lock :: proc(m: ^Mutex) {
  15. _mutex_lock(m)
  16. }
  17. // mutex_unlock unlocks m
  18. mutex_unlock :: proc(m: ^Mutex) {
  19. _mutex_unlock(m)
  20. }
  21. // mutex_try_lock tries to lock m, will return true on success, and false on failure
  22. mutex_try_lock :: proc(m: ^Mutex) -> bool {
  23. return _mutex_try_lock(m)
  24. }
  25. /*
  26. Example:
  27. if mutex_guard(&m) {
  28. ...
  29. }
  30. */
  31. @(deferred_in=mutex_unlock)
  32. mutex_guard :: proc(m: ^Mutex) -> bool {
  33. mutex_lock(m)
  34. return true
  35. }
  36. // A RW_Mutex is a reader/writer mutual exclusion lock
  37. // The lock can be held by any arbitrary number of readers or a single writer
  38. // The zero value for a RW_Mutex is an unlocked mutex
  39. //
  40. // A RW_Mutex must not be copied after first use
  41. RW_Mutex :: struct {
  42. impl: _RW_Mutex,
  43. }
  44. // rw_mutex_lock locks rw for writing (with a single writer)
  45. // If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available.
  46. rw_mutex_lock :: proc(rw: ^RW_Mutex) {
  47. _rw_mutex_lock(rw)
  48. }
  49. // rw_mutex_unlock unlocks rw for writing (with a single writer)
  50. rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
  51. _rw_mutex_unlock(rw)
  52. }
  53. // rw_mutex_try_lock tries to lock rw for writing (with a single writer)
  54. rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
  55. return _rw_mutex_try_lock(rw)
  56. }
  57. // rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers)
  58. rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
  59. _rw_mutex_shared_lock(rw)
  60. }
  61. // rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers)
  62. rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
  63. _rw_mutex_shared_unlock(rw)
  64. }
  65. // rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers)
  66. rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
  67. return _rw_mutex_try_shared_lock(rw)
  68. }
  69. /*
  70. Example:
  71. if rw_mutex_guard(&m) {
  72. ...
  73. }
  74. */
  75. @(deferred_in=rw_mutex_unlock)
  76. rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool {
  77. rw_mutex_lock(m)
  78. return true
  79. }
  80. /*
  81. Example:
  82. if rw_mutex_shared_guard(&m) {
  83. ...
  84. }
  85. */
  86. @(deferred_in=rw_mutex_shared_unlock)
  87. rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool {
  88. rw_mutex_shared_lock(m)
  89. return true
  90. }
  91. // A Recursive_Mutex is a recursive mutual exclusion lock
  92. // The zero value for a Recursive_Mutex is an unlocked mutex
  93. //
  94. // A Recursive_Mutex must not be copied after first use
  95. Recursive_Mutex :: struct {
  96. impl: _Recursive_Mutex,
  97. }
  98. recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
  99. _recursive_mutex_lock(m)
  100. }
  101. recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
  102. _recursive_mutex_unlock(m)
  103. }
  104. recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
  105. return _recursive_mutex_try_lock(m)
  106. }
  107. /*
  108. Example:
  109. if recursive_mutex_guard(&m) {
  110. ...
  111. }
  112. */
  113. @(deferred_in=recursive_mutex_unlock)
  114. recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool {
  115. recursive_mutex_lock(m)
  116. return true
  117. }
  118. // Cond implements a condition variable, a rendezvous point for threads
  119. // waiting for signalling the occurence of an event
  120. //
  121. // A Cond must not be copied after first use
  122. Cond :: struct {
  123. impl: _Cond,
  124. }
  125. cond_wait :: proc(c: ^Cond, m: ^Mutex) {
  126. _cond_wait(c, m)
  127. }
  128. cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
  129. if duration <= 0 {
  130. return false
  131. }
  132. return _cond_wait_with_timeout(c, m, duration)
  133. }
  134. cond_signal :: proc(c: ^Cond) {
  135. _cond_signal(c)
  136. }
  137. cond_broadcast :: proc(c: ^Cond) {
  138. _cond_broadcast(c)
  139. }
  140. // When waited upon, blocks until the internal count is greater than zero, then subtracts one.
  141. // Posting to the semaphore increases the count by one, or the provided amount.
  142. //
  143. // A Sema must not be copied after first use
  144. Sema :: struct {
  145. impl: _Sema,
  146. }
  147. sema_post :: proc(s: ^Sema, count := 1) {
  148. _sema_post(s, count)
  149. }
  150. sema_wait :: proc(s: ^Sema) {
  151. _sema_wait(s)
  152. }
  153. sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool {
  154. return _sema_wait_with_timeout(s, duration)
  155. }
  156. // Futex is a fast userspace mutual exclusion lock, using a 32-bit memory address as a hint
  157. //
  158. // An Futex must not be copied after first use
  159. Futex :: distinct u32
  160. futex_wait :: proc(f: ^Futex, expected: u32) {
  161. if u32(atomic_load(f)) != expected {
  162. return
  163. }
  164. assert(_futex_wait(f, expected), "futex_wait failure")
  165. }
  166. // returns true if the wait happened within the duration, false if it exceeded the time duration
  167. futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool {
  168. if u32(atomic_load(f)) != expected {
  169. return true
  170. }
  171. if duration <= 0 {
  172. return false
  173. }
  174. return _futex_wait_with_timeout(f, expected, duration)
  175. }
  176. futex_signal :: proc(f: ^Futex) {
  177. _futex_signal(f)
  178. }
  179. futex_broadcast :: proc(f: ^Futex) {
  180. _futex_broadcast(f)
  181. }