Browse Source

Add `thread.run*` shorthand procedures; `Thread.init_context` use new `Maybe` concept

gingerBill 5 years ago
parent
commit
b3c51a8b44
4 changed files with 61 additions and 23 deletions
  1. 40 2
      core/thread/thread.odin
  2. 3 3
      core/thread/thread_unix.odin
  3. 18 17
      core/thread/thread_windows.odin
  4. 0 1
      examples/demo/demo.odin

+ 40 - 2
core/thread/thread.odin

@@ -1,6 +1,8 @@
 package thread
 
 import "core:runtime"
+import "core:os"
+import "core:sync"
 
 Thread_Proc :: #type proc(^Thread);
 
@@ -10,6 +12,42 @@ Thread :: struct {
 	data:             rawptr,
 	user_index:       int,
 
-	init_context:     runtime.Context,
-	use_init_context: bool,
+	init_context: Maybe(runtime.Context),
+}
+
+#assert(size_of(Thread{}.user_index) == size_of(uintptr));
+
+
+run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
+	thread_proc :: proc(t: ^Thread) {
+		fn := cast(proc())t.data;
+		fn();
+		destroy(t);
+	}
+	t := create(thread_proc, priority);
+	t.data = rawptr(fn);
+	t.init_context = init_context;
+	start(t);
+}
+
+
+run_with_data :: proc(fn: proc(data: rawptr), data: rawptr, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
+	thread_proc :: proc(t: ^Thread) {
+		fn := cast(proc(rawptr))t.data;
+		data := rawptr(uintptr(t.user_index));
+		fn(data);
+		destroy(t);
+	}
+	t := create(thread_proc, priority);
+	t.data = rawptr(fn);
+	t.user_index = int(uintptr(data));
+	t.init_context = init_context;
+	start(t);
+}
+
+
+run_with_thread_proc :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
+	t := create(fn, priority);
+	t.init_context = init_context;
+	start(t);
 }

+ 3 - 3
core/thread/thread_unix.odin

@@ -51,14 +51,14 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T
 		t.start_gate = {};
 
 		c := context;
-		if t.use_init_context {
-			c = t.init_context;
+		if ic, ok := t.init_context.?; ok {
+			c = ic;
 		}
 		context = c;
 
 		t.procedure(t);
 
-		if !t.use_init_context {
+		if t.init_context == nil {
 			if context.temp_allocator.data == &runtime.global_default_temp_allocator_data {
 				runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data);
 			}

+ 18 - 17
core/thread/thread_windows.odin

@@ -10,33 +10,33 @@ Thread_Os_Specific :: struct {
 	done: bool, // see note in `is_done`
 }
 
-THREAD_PRIORITY_IDLE   :: -15;
-THREAD_PRIORITY_LOWEST :: -2;
-THREAD_PRIORITY_BELOW_NORMAL :: -1;
-THREAD_PRIORITY_NORMAL :: 0;
-THREAD_PRIORITY_ABOVE_NORMAL :: 1;
-THREAD_PRIORITY_HIGHEST :: 2;
-THREAD_PRIORITY_TIME_CRITICAL :: 15;
-
-Thread_Priority :: enum i32 {
-	Normal = THREAD_PRIORITY_NORMAL,
-	Low = THREAD_PRIORITY_LOWEST,
-	High = THREAD_PRIORITY_HIGHEST,
+
+Thread_Priority :: enum {
+	Normal,
+	Low,
+	High,
 }
 
+_thread_priority_map := map[Thread_Priority]i32{
+	.Normal = 0,
+	.Low = -2,
+	.High = +2,
+};
+
 create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
 	win32_thread_id: u32;
 
 	__windows_thread_entry_proc :: proc "c" (t: ^Thread) -> i32 {
-		c := runtime.default_context();
-		if t.use_init_context {
-			c = t.init_context;
+		context = runtime.default_context();
+		c := context;
+		if ic, ok := t.init_context.?; ok {
+			c = ic;
 		}
 		context = c;
 
 		t.procedure(t);
 
-		if !t.use_init_context {
+		if t.init_context == nil {
 			if context.temp_allocator.data == &runtime.global_default_temp_allocator_data {
 				runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data);
 			}
@@ -58,8 +58,9 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T
 	thread.procedure       = procedure;
 	thread.win32_thread    = win32_thread;
 	thread.win32_thread_id = win32_thread_id;
+	thread.init_context = context;
 
-	ok := win32.set_thread_priority(win32_thread, i32(priority));
+	ok := win32.set_thread_priority(win32_thread, _thread_priority_map[priority]);
 	assert(ok == true);
 
 	return thread;

+ 0 - 1
examples/demo/demo.odin

@@ -1120,7 +1120,6 @@ threading_example :: proc() {
 		for in prefix_table {
 			if t := thread.create(worker_proc); t != nil {
 				t.init_context = context;
-				t.use_init_context = true;
 				t.user_index = len(threads);
 				append(&threads, t);
 				thread.start(t);