thread.odin 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package thread
  2. import "core:runtime"
  3. import "core:mem"
  4. import "intrinsics"
  5. _ :: intrinsics;
  6. Thread_Proc :: #type proc(^Thread);
  7. MAX_USER_ARGUMENTS :: 8;
  8. Thread :: struct {
  9. using specific: Thread_Os_Specific,
  10. procedure: Thread_Proc,
  11. data: rawptr,
  12. user_index: int,
  13. user_args: [MAX_USER_ARGUMENTS]rawptr,
  14. init_context: Maybe(runtime.Context),
  15. creation_allocator: mem.Allocator,
  16. }
  17. #assert(size_of(Thread{}.user_index) == size_of(uintptr));
  18. Thread_Priority :: enum {
  19. Normal,
  20. Low,
  21. High,
  22. }
  23. create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
  24. return _create(procedure, priority);
  25. }
  26. destroy :: proc(thread: ^Thread) {
  27. _destroy(thread);
  28. }
  29. start :: proc(thread: ^Thread) {
  30. _start(thread);
  31. }
  32. is_done :: proc(thread: ^Thread) -> bool {
  33. return _is_done(thread);
  34. }
  35. join :: proc(thread: ^Thread) {
  36. _join(thread);
  37. }
  38. join_mulitple :: proc(threads: ..^Thread) {
  39. _join_multiple(..threads);
  40. }
  41. terminate :: proc(thread: ^Thread, exit_code: int) {
  42. _terminate(thread, exit_code);
  43. }
  44. yield :: proc() {
  45. _yield();
  46. }
  47. run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  48. thread_proc :: proc(t: ^Thread) {
  49. fn := cast(proc())t.data;
  50. fn();
  51. destroy(t);
  52. }
  53. t := create(thread_proc, priority);
  54. t.data = rawptr(fn);
  55. t.init_context = init_context;
  56. start(t);
  57. }
  58. run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  59. thread_proc :: proc(t: ^Thread) {
  60. fn := cast(proc(rawptr))t.data;
  61. assert(t.user_index >= 1);
  62. data := t.user_args[0];
  63. fn(data);
  64. destroy(t);
  65. }
  66. t := create(thread_proc, priority);
  67. t.data = rawptr(fn);
  68. t.user_index = 1;
  69. t.user_args = data;
  70. t.init_context = init_context;
  71. start(t);
  72. }
  73. run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  74. where size_of(T) <= size_of(rawptr) {
  75. thread_proc :: proc(t: ^Thread) {
  76. fn := cast(proc(T))t.data;
  77. assert(t.user_index >= 1);
  78. data := (^T)(&t.user_args[0])^;
  79. fn(data);
  80. destroy(t);
  81. }
  82. t := create(thread_proc, priority);
  83. t.data = rawptr(fn);
  84. t.user_index = 1;
  85. data := data;
  86. mem.copy(&t.user_args[0], &data, size_of(data));
  87. t.init_context = init_context;
  88. start(t);
  89. }
  90. run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
  91. where size_of(T1) <= size_of(rawptr),
  92. size_of(T2) <= size_of(rawptr) {
  93. thread_proc :: proc(t: ^Thread) {
  94. fn := cast(proc(T1, T2))t.data;
  95. assert(t.user_index >= 2);
  96. arg1 := (^T1)(&t.user_args[0])^;
  97. arg2 := (^T2)(&t.user_args[1])^;
  98. fn(arg1, arg2);
  99. destroy(t);
  100. }
  101. t := create(thread_proc, priority);
  102. t.data = rawptr(fn);
  103. t.user_index = 2;
  104. arg1, arg2 := arg1, arg2;
  105. mem.copy(&t.user_args[0], &arg1, size_of(arg1));
  106. mem.copy(&t.user_args[1], &arg2, size_of(arg2));
  107. t.init_context = init_context;
  108. start(t);
  109. }
  110. 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)
  111. where size_of(T1) <= size_of(rawptr),
  112. size_of(T2) <= size_of(rawptr),
  113. size_of(T3) <= size_of(rawptr) {
  114. thread_proc :: proc(t: ^Thread) {
  115. fn := cast(proc(T1, T2, T3))t.data;
  116. assert(t.user_index >= 3);
  117. arg1 := (^T1)(&t.user_args[0])^;
  118. arg2 := (^T2)(&t.user_args[1])^;
  119. arg3 := (^T3)(&t.user_args[2])^;
  120. fn(arg1, arg2, arg3);
  121. destroy(t);
  122. }
  123. t := create(thread_proc, priority);
  124. t.data = rawptr(fn);
  125. t.user_index = 3;
  126. arg1, arg2, arg3 := arg1, arg2, arg3;
  127. mem.copy(&t.user_args[0], &arg1, size_of(arg1));
  128. mem.copy(&t.user_args[1], &arg2, size_of(arg2));
  129. mem.copy(&t.user_args[2], &arg3, size_of(arg3));
  130. t.init_context = init_context;
  131. start(t);
  132. }
  133. 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)
  134. where size_of(T1) <= size_of(rawptr),
  135. size_of(T2) <= size_of(rawptr),
  136. size_of(T3) <= size_of(rawptr) {
  137. thread_proc :: proc(t: ^Thread) {
  138. fn := cast(proc(T1, T2, T3, T4))t.data;
  139. assert(t.user_index >= 4);
  140. arg1 := (^T1)(&t.user_args[0])^;
  141. arg2 := (^T2)(&t.user_args[1])^;
  142. arg3 := (^T3)(&t.user_args[2])^;
  143. arg4 := (^T4)(&t.user_args[3])^;
  144. fn(arg1, arg2, arg3, arg4);
  145. destroy(t);
  146. }
  147. t := create(thread_proc, priority);
  148. t.data = rawptr(fn);
  149. t.user_index = 4;
  150. arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4;
  151. mem.copy(&t.user_args[0], &arg1, size_of(arg1));
  152. mem.copy(&t.user_args[1], &arg2, size_of(arg2));
  153. mem.copy(&t.user_args[2], &arg3, size_of(arg3));
  154. mem.copy(&t.user_args[3], &arg4, size_of(arg4));
  155. t.init_context = init_context;
  156. start(t);
  157. }
  158. create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread {
  159. t := create(fn, priority);
  160. t.init_context = init_context;
  161. start(t);
  162. return t;
  163. }