Browse Source

Fix joining non-`Started` threads from blocking main thread

Feoramund 1 year ago
parent
commit
33c6f75a2e
2 changed files with 19 additions and 2 deletions
  1. 9 0
      core/thread/thread_unix.odin
  2. 10 2
      core/thread/thread_windows.odin

+ 9 - 0
core/thread/thread_unix.odin

@@ -36,6 +36,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
 			sync.wait(&t.cond, &t.mutex)
 		}
 
+		if .Joined in t.flags {
+			return nil
+		}
+
 		when ODIN_OS != .Darwin {
 			// Enable thread's cancelability.
 			if can_set_thread_cancel_state {
@@ -143,6 +147,11 @@ _join :: proc(t: ^Thread) {
 	if res, ok := CAS(&t.flags, unjoined, joined); res == joined && !ok {
 		return
 	}
+	// Prevent non-started threads from blocking main thread with initial wait
+	// condition.
+	if .Started not_in unjoined {
+		_start(t)
+	}
 	unix.pthread_join(t.unix_thread, nil)
 }
 

+ 10 - 2
core/thread/thread_windows.odin

@@ -24,6 +24,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
 	__windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD {
 		t := (^Thread)(t_)
 
+		if .Joined in t.flags {
+			return 0
+		}
+
 		t.id = sync.current_thread_id()
 
 		{
@@ -93,11 +97,15 @@ _join :: proc(t: ^Thread) {
 		return
 	}
 
+	t.flags += {.Joined}
+
+	if .Started not_in t.flags {
+		_start(t)
+	}
+
 	win32.WaitForSingleObject(t.win32_thread, win32.INFINITE)
 	win32.CloseHandle(t.win32_thread)
 	t.win32_thread = win32.INVALID_HANDLE
-
-	t.flags += {.Joined}
 }
 
 _join_multiple :: proc(threads: ..^Thread) {