thread.odin 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package thread
  2. import "core:runtime"
  3. import "core:sync"
  4. import "core:intrinsics"
  5. Thread_Proc :: #type proc(^Thread);
  6. Thread :: struct {
  7. using specific: Thread_Os_Specific,
  8. procedure: Thread_Proc,
  9. data: rawptr,
  10. user_index: int,
  11. init_context: Maybe(runtime.Context),
  12. }
  13. #assert(size_of(Thread{}.user_index) == size_of(uintptr));
  14. run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  15. thread_proc :: proc(t: ^Thread) {
  16. fn := cast(proc())t.data;
  17. fn();
  18. destroy(t);
  19. }
  20. t := create(thread_proc, priority);
  21. t.data = rawptr(fn);
  22. t.init_context = init_context;
  23. start(t);
  24. }
  25. run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
  26. thread_proc :: proc(t: ^Thread) {
  27. fn := cast(proc(rawptr))t.data;
  28. data := rawptr(uintptr(t.user_index));
  29. fn(data);
  30. destroy(t);
  31. }
  32. t := create(thread_proc, priority);
  33. t.data = rawptr(fn);
  34. t.user_index = int(uintptr(data));
  35. t.init_context = init_context;
  36. start(t);
  37. }
  38. create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread {
  39. t := create(fn, priority);
  40. t.init_context = init_context;
  41. start(t);
  42. return t;
  43. }
  44. Once :: struct {
  45. m: sync.Blocking_Mutex,
  46. done: bool,
  47. }
  48. once_init :: proc(o: ^Once) {
  49. sync.blocking_mutex_init(&o.m);
  50. intrinsics.atomic_store_rel(&o.done, false);
  51. }
  52. once_destroy :: proc(o: ^Once) {
  53. sync.blocking_mutex_destroy(&o.m);
  54. }
  55. once_do :: proc(o: ^Once, fn: proc()) {
  56. if intrinsics.atomic_load(&o.done) == false {
  57. _once_do_slow(o, fn);
  58. }
  59. }
  60. _once_do_slow :: proc(o: ^Once, fn: proc()) {
  61. sync.blocking_mutex_lock(&o.m);
  62. defer sync.blocking_mutex_unlock(&o.m);
  63. if !o.done {
  64. fn();
  65. intrinsics.atomic_store_rel(&o.done, true);
  66. }
  67. }