thread.odin 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package thread
  2. import "core:runtime"
  3. import "core:mem"
  4. import "core:intrinsics"
  5. _ :: intrinsics
  6. Thread_Proc :: #type proc(^Thread)
  7. MAX_USER_ARGUMENTS :: 8
  8. Thread :: struct {
  9. using specific: Thread_Os_Specific,
  10. id: int,
  11. procedure: Thread_Proc,
  12. data: rawptr,
  13. user_index: int,
  14. user_args: [MAX_USER_ARGUMENTS]rawptr,
  15. init_context: Maybe(runtime.Context),
  16. creation_allocator: mem.Allocator,
  17. }
  18. #assert(size_of(Thread{}.user_index) == size_of(uintptr))
  19. Thread_Priority :: enum {
  20. Normal,
  21. Low,
  22. High,
  23. }
  24. create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
  25. return _create(procedure, priority)
  26. }
  27. destroy :: proc(thread: ^Thread) {
  28. _destroy(thread)
  29. }
  30. start :: proc(thread: ^Thread) {
  31. _start(thread)
  32. }
  33. is_done :: proc(thread: ^Thread) -> bool {
  34. return _is_done(thread)
  35. }
  36. join :: proc(thread: ^Thread) {
  37. _join(thread)
  38. }
  39. join_multiple :: proc(threads: ..^Thread) {
  40. _join_multiple(..threads)
  41. }
  42. terminate :: proc(thread: ^Thread, exit_code: int) {
  43. _terminate(thread, exit_code)
  44. }
  45. yield :: proc() {
  46. _yield()
  47. }
  48. run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  49. thread_proc :: proc(t: ^Thread) {
  50. fn := cast(proc())t.data
  51. fn()
  52. destroy(t)
  53. }
  54. t := create(thread_proc, priority)
  55. t.data = rawptr(fn)
  56. t.init_context = init_context
  57. start(t)
  58. }
  59. run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  60. thread_proc :: proc(t: ^Thread) {
  61. fn := cast(proc(rawptr))t.data
  62. assert(t.user_index >= 1)
  63. data := t.user_args[0]
  64. fn(data)
  65. destroy(t)
  66. }
  67. t := create(thread_proc, priority)
  68. t.data = rawptr(fn)
  69. t.user_index = 1
  70. t.user_args = data
  71. t.init_context = init_context
  72. start(t)
  73. }
  74. run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  75. where size_of(T) <= size_of(rawptr) {
  76. thread_proc :: proc(t: ^Thread) {
  77. fn := cast(proc(T))t.data
  78. assert(t.user_index >= 1)
  79. data := (^T)(&t.user_args[0])^
  80. fn(data)
  81. destroy(t)
  82. }
  83. t := create(thread_proc, priority)
  84. t.data = rawptr(fn)
  85. t.user_index = 1
  86. data := data
  87. mem.copy(&t.user_args[0], &data, size_of(data))
  88. t.init_context = init_context
  89. start(t)
  90. }
  91. run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  92. where size_of(T1) <= size_of(rawptr),
  93. size_of(T2) <= size_of(rawptr) {
  94. thread_proc :: proc(t: ^Thread) {
  95. fn := cast(proc(T1, T2))t.data
  96. assert(t.user_index >= 2)
  97. arg1 := (^T1)(&t.user_args[0])^
  98. arg2 := (^T2)(&t.user_args[1])^
  99. fn(arg1, arg2)
  100. destroy(t)
  101. }
  102. t := create(thread_proc, priority)
  103. t.data = rawptr(fn)
  104. t.user_index = 2
  105. arg1, arg2 := arg1, arg2
  106. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  107. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  108. t.init_context = init_context
  109. start(t)
  110. }
  111. run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  112. where size_of(T1) <= size_of(rawptr),
  113. size_of(T2) <= size_of(rawptr),
  114. size_of(T3) <= size_of(rawptr) {
  115. thread_proc :: proc(t: ^Thread) {
  116. fn := cast(proc(T1, T2, T3))t.data
  117. assert(t.user_index >= 3)
  118. arg1 := (^T1)(&t.user_args[0])^
  119. arg2 := (^T2)(&t.user_args[1])^
  120. arg3 := (^T3)(&t.user_args[2])^
  121. fn(arg1, arg2, arg3)
  122. destroy(t)
  123. }
  124. t := create(thread_proc, priority)
  125. t.data = rawptr(fn)
  126. t.user_index = 3
  127. arg1, arg2, arg3 := arg1, arg2, arg3
  128. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  129. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  130. mem.copy(&t.user_args[2], &arg3, size_of(arg3))
  131. t.init_context = init_context
  132. start(t)
  133. }
  134. run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  135. where size_of(T1) <= size_of(rawptr),
  136. size_of(T2) <= size_of(rawptr),
  137. size_of(T3) <= size_of(rawptr) {
  138. thread_proc :: proc(t: ^Thread) {
  139. fn := cast(proc(T1, T2, T3, T4))t.data
  140. assert(t.user_index >= 4)
  141. arg1 := (^T1)(&t.user_args[0])^
  142. arg2 := (^T2)(&t.user_args[1])^
  143. arg3 := (^T3)(&t.user_args[2])^
  144. arg4 := (^T4)(&t.user_args[3])^
  145. fn(arg1, arg2, arg3, arg4)
  146. destroy(t)
  147. }
  148. t := create(thread_proc, priority)
  149. t.data = rawptr(fn)
  150. t.user_index = 4
  151. arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4
  152. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  153. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  154. mem.copy(&t.user_args[2], &arg3, size_of(arg3))
  155. mem.copy(&t.user_args[3], &arg4, size_of(arg4))
  156. t.init_context = init_context
  157. start(t)
  158. }
  159. create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread {
  160. t := create(fn, priority)
  161. t.init_context = init_context
  162. start(t)
  163. return t
  164. }
  165. create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread {
  166. thread_proc :: proc(t: ^Thread) {
  167. fn := cast(proc(rawptr))t.data
  168. assert(t.user_index >= 1)
  169. data := t.user_args[0]
  170. fn(data)
  171. }
  172. t := create(thread_proc, priority)
  173. t.data = rawptr(fn)
  174. t.user_index = 1
  175. t.user_args = data
  176. t.init_context = init_context
  177. start(t)
  178. return t
  179. }
  180. create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread
  181. where size_of(T) <= size_of(rawptr) {
  182. thread_proc :: proc(t: ^Thread) {
  183. fn := cast(proc(T))t.data
  184. assert(t.user_index >= 1)
  185. data := (^T)(&t.user_args[0])^
  186. fn(data)
  187. }
  188. t := create(thread_proc, priority)
  189. t.data = rawptr(fn)
  190. t.user_index = 1
  191. data := data
  192. mem.copy(&t.user_args[0], &data, size_of(data))
  193. t.init_context = init_context
  194. start(t)
  195. return t
  196. }
  197. create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread
  198. where size_of(T1) <= size_of(rawptr),
  199. size_of(T2) <= size_of(rawptr) {
  200. thread_proc :: proc(t: ^Thread) {
  201. fn := cast(proc(T1, T2))t.data
  202. assert(t.user_index >= 2)
  203. arg1 := (^T1)(&t.user_args[0])^
  204. arg2 := (^T2)(&t.user_args[1])^
  205. fn(arg1, arg2)
  206. }
  207. t := create(thread_proc, priority)
  208. t.data = rawptr(fn)
  209. t.user_index = 2
  210. arg1, arg2 := arg1, arg2
  211. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  212. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  213. t.init_context = init_context
  214. start(t)
  215. return t
  216. }
  217. create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread
  218. where size_of(T1) <= size_of(rawptr),
  219. size_of(T2) <= size_of(rawptr),
  220. size_of(T3) <= size_of(rawptr) {
  221. thread_proc :: proc(t: ^Thread) {
  222. fn := cast(proc(T1, T2, T3))t.data
  223. assert(t.user_index >= 3)
  224. arg1 := (^T1)(&t.user_args[0])^
  225. arg2 := (^T2)(&t.user_args[1])^
  226. arg3 := (^T3)(&t.user_args[2])^
  227. fn(arg1, arg2, arg3)
  228. }
  229. t := create(thread_proc, priority)
  230. t.data = rawptr(fn)
  231. t.user_index = 3
  232. arg1, arg2, arg3 := arg1, arg2, arg3
  233. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  234. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  235. mem.copy(&t.user_args[2], &arg3, size_of(arg3))
  236. t.init_context = init_context
  237. start(t)
  238. return t
  239. }
  240. create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread
  241. where size_of(T1) <= size_of(rawptr),
  242. size_of(T2) <= size_of(rawptr),
  243. size_of(T3) <= size_of(rawptr) {
  244. thread_proc :: proc(t: ^Thread) {
  245. fn := cast(proc(T1, T2, T3, T4))t.data
  246. assert(t.user_index >= 4)
  247. arg1 := (^T1)(&t.user_args[0])^
  248. arg2 := (^T2)(&t.user_args[1])^
  249. arg3 := (^T3)(&t.user_args[2])^
  250. arg4 := (^T4)(&t.user_args[3])^
  251. fn(arg1, arg2, arg3, arg4)
  252. }
  253. t := create(thread_proc, priority)
  254. t.data = rawptr(fn)
  255. t.user_index = 4
  256. arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4
  257. mem.copy(&t.user_args[0], &arg1, size_of(arg1))
  258. mem.copy(&t.user_args[1], &arg2, size_of(arg2))
  259. mem.copy(&t.user_args[2], &arg3, size_of(arg3))
  260. mem.copy(&t.user_args[3], &arg4, size_of(arg4))
  261. t.init_context = init_context
  262. start(t)
  263. return t
  264. }