Quellcode durchsuchen

changed threads init code to be available during static inits (fixes #10114)

Aleksandr Kuzmenko vor 4 Jahren
Ursprung
Commit
d080be2a93

+ 6 - 0
extra/CHANGES.txt

@@ -1,3 +1,9 @@
+2021-XX-XX 4.2.1:
+
+	Bugfixes:
+
+	threads : changed main thread initialization to make main event loop available during static initialization (#10114)
+
 2021-02-09 4.2.0:
 
 	New features:

+ 2 - 9
src/typing/finalization.ml

@@ -59,17 +59,10 @@ let get_main ctx types =
 				[main; call_static (["haxe"],"EntryPoint") "run"]
 			with Not_found ->
 				[main]
-		and add_entry_point_init main =
-			try
-				[call_static (["haxe"],"EntryPoint") "init"; main]
-			with Not_found ->
-				[main]
-		in
 		(* add calls for event loop *)
-		let add_event_loop main =
+		and add_event_loop main =
 			(try
-				let thread = (["sys";"thread";"_Thread"],"Thread_Impl_") in
-				call_static thread "initEventLoop" :: add_entry_point_init main @ [call_static thread "processEvents"]
+				[main; call_static (["sys";"thread";"_Thread"],"Thread_Impl_") "processEvents"]
 			with Not_found ->
 				[main]
 			)

+ 12 - 9
std/cpp/_std/sys/thread/Thread.hx

@@ -57,11 +57,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		@:privateAccess HaxeThread.current().events = new EventLoop();
-	}
-
 	@:keep
 	static public function processEvents() {
 		HaxeThread.current().events.loop();
@@ -76,10 +71,18 @@ private typedef ThreadHandle = NativeThreadHandle;
 
 
 private class HaxeThread {
-	static final threads = new Array<{thread:HaxeThread, handle:ThreadHandle}>();
-	static final threadsMutex = new Mutex();
-	static var mainThreadHandle:ThreadHandle = currentHandle();
-	static var mainThread:HaxeThread = new HaxeThread(currentHandle());
+	static var threads:Array<{thread:HaxeThread, handle:ThreadHandle}>;
+	static var threadsMutex:Mutex;
+	static var mainThreadHandle:ThreadHandle;
+	static var mainThread:HaxeThread;
+
+	static function __init__() {
+		threads = [];
+		threadsMutex = new Mutex();
+		mainThreadHandle = currentHandle();
+		mainThread = new HaxeThread(currentHandle());		
+		mainThread.events = new EventLoop();
+	}
 
 	public var events(default,null):Null<EventLoop>;
 	public var handle:ThreadHandle;

+ 15 - 10
std/cs/_std/sys/thread/Thread.hx

@@ -23,6 +23,7 @@
 package sys.thread;
 
 import cs.system.threading.Thread as NativeThread;
+import cs.system.threading.Mutex as NativeMutex;
 import cs.system.WeakReference;
 import cs.Lib;
 
@@ -88,11 +89,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop():Void {
-		@:privateAccess HaxeThread.get(NativeThread.CurrentThread).events = new EventLoop();
-	}
-
 	@:keep
 	static function processEvents():Void {
 		HaxeThread.get(NativeThread.CurrentThread).events.loop();
@@ -100,11 +96,20 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 }
 
 private class HaxeThread {
-	static final mainNativeThread = NativeThread.CurrentThread;
-	static final mainHaxeThread = new HaxeThread(NativeThread.CurrentThread);
-	static final threads = new Map<Int, WeakReference>();
-	static final threadsMutex = new cs.system.threading.Mutex();
-	static var allocateCount = 0;
+	static var mainNativeThread:NativeThread;
+	static var mainHaxeThread:HaxeThread;
+	static var threads:Map<Int, WeakReference>;
+	static var threadsMutex:NativeMutex;
+	static var allocateCount:Int;
+
+	static function __init__() {
+		threads = new Map();
+		threadsMutex = new NativeMutex();
+		allocateCount = 0;
+		mainNativeThread = NativeThread.CurrentThread;
+		mainHaxeThread = new HaxeThread(NativeThread.CurrentThread);
+		mainHaxeThread.events = new EventLoop();
+	}
 
 	public final native:NativeThread;
 	public var events(default,null):Null<EventLoop>;

+ 4 - 6
std/eval/_std/sys/thread/Thread.hx

@@ -29,6 +29,10 @@ private typedef ThreadImpl = NativeThread;
 abstract Thread(ThreadImpl) from ThreadImpl {
 	public var events(get,never):EventLoop;
 
+	static function __init__() {
+		NativeThread.self().events = new EventLoop();
+	}
+
 	inline function new(h:NativeThread):Void {
 		this = h;
 	}
@@ -94,12 +98,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		NativeThread.self().events = new EventLoop();
-	}
-
-
 	@:keep
 	static function processEvents():Void {
 		NativeThread.self().events.loop();

+ 1 - 4
std/haxe/EntryPoint.hx

@@ -36,10 +36,7 @@ class EntryPoint {
 	#if sys
 		static var mutex = new Mutex();
 		#if (target.threaded && !cppia)
-			static var mainThread:Thread;
-			@:keep static function init() {
-				mainThread = Thread.current();
-			}
+			static var mainThread:Thread = Thread.current();
 		#else
 			static var sleepLock = new Lock();
 		#end

+ 1 - 3
std/haxe/MainLoop.hx

@@ -63,9 +63,7 @@ class MainLoop {
 	#if (target.threaded && !cppia)
 	static var eventLoopHandler:Null<EventHandler>;
 	static var mutex = new sys.thread.Mutex();
-	static var mainThread(get,never):Thread;
-	static inline function get_mainThread():Thread
-		return @:privateAccess EntryPoint.mainThread;
+	static var mainThread = Thread.current();
 	#end
 
 	static var pending:MainEvent;

+ 12 - 9
std/hl/_std/sys/thread/Thread.hx

@@ -57,11 +57,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		@:privateAccess HaxeThread.current().events = new EventLoop();
-	}
-
 	@:keep
 	static public function processEvents() {
 		HaxeThread.current().events.loop();
@@ -71,10 +66,18 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 private typedef ThreadHandle = hl.Abstract<"hl_thread">;
 
 private class HaxeThread {
-	static final mainThreadHandle:ThreadHandle = currentHandle();
-	static final mainThread:HaxeThread = new HaxeThread();
-	static final threads = new Array<{thread:HaxeThread, handle:ThreadHandle}>();
-	static final threadsMutex = new Mutex();
+	static var mainThreadHandle:ThreadHandle;
+	static var mainThread:HaxeThread;
+	static var threads:Array<{thread:HaxeThread, handle:ThreadHandle}>;
+	static var threadsMutex:Mutex;
+
+	static function __init__() {
+		mainThreadHandle = currentHandle();
+		threadsMutex = new Mutex();
+		threads = [];
+		mainThread = new HaxeThread();
+		mainThread.events = new EventLoop();
+	}
 
 	public var events(default,null):Null<EventLoop>;
 	final messages = new Deque();

+ 10 - 8
std/java/_std/sys/thread/Thread.hx

@@ -75,11 +75,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		@:privateAccess HaxeThread.get(JavaThread.currentThread()).events = new EventLoop();
-	}
-
 	@:keep //TODO: keep only if events are actually used
 	static function processEvents():Void {
 		current().getHandle().events.loop();
@@ -87,9 +82,16 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 }
 
 private class HaxeThread {
-	static final nativeThreads = Collections.synchronizedMap(new WeakHashMap<JavaThread,HaxeThread>());
-	static final mainJavaThread = JavaThread.currentThread();
-	static final mainHaxeThread = new HaxeThread();
+	static var nativeThreads:java.util.Map<JavaThread,HaxeThread>;
+	static var mainJavaThread:JavaThread;
+	static var mainHaxeThread:HaxeThread;
+
+	static function __init__() {
+		nativeThreads = Collections.synchronizedMap(new WeakHashMap<JavaThread,HaxeThread>());
+		mainJavaThread = JavaThread.currentThread();
+		mainHaxeThread = new HaxeThread();
+		mainHaxeThread.events = new EventLoop();
+	}
 
 	public final messages = new LinkedBlockingDeque<Dynamic>();
 

+ 22 - 13
std/neko/_std/sys/thread/Thread.hx

@@ -58,11 +58,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		@:privateAccess HaxeThread.current().events = new EventLoop();
-	}
-
 	@:keep
 	static function processEvents() {
 		HaxeThread.current().events.loop();
@@ -76,16 +71,30 @@ private abstract NativeThreadHandle {}
 private typedef ThreadHandle = NativeThreadHandle;
 
 private class HaxeThread {
-	static var thread_create:(callb:(_:Dynamic)->Void, _:Dynamic)->ThreadHandle = neko.Lib.load("std", "thread_create", 2);
-	static var thread_current:()->ThreadHandle = neko.Lib.load("std", "thread_current", 0);
-	static var thread_send:(handle:ThreadHandle, msg:Dynamic)->Void = neko.Lib.load("std", "thread_send", 2);
-	static var thread_read_message:(block:Bool)->Dynamic = neko.Lib.load("std", "thread_read_message", 1);
+	static var thread_create:(callb:(_:Dynamic)->Void, _:Dynamic)->ThreadHandle;
+	static var thread_current:()->ThreadHandle;
+	static var thread_send:(handle:ThreadHandle, msg:Dynamic)->Void;
+	static var thread_read_message:(block:Bool)->Dynamic;
+
+	static var mainThreadHandle:ThreadHandle;
+	static var mainThread:HaxeThread;
 
-	static var mainThreadHandle = thread_current();
-	static var mainThread = new HaxeThread(mainThreadHandle);
+	static var threads:Array<{thread:HaxeThread, handle:ThreadHandle}>;
+	static var threadsMutex:Mutex;
 
-	static final threads = new Array<{thread:HaxeThread, handle:ThreadHandle}>();
-	static final threadsMutex = new Mutex();
+	static function __init__() {
+		thread_create = neko.Lib.load("std", "thread_create", 2);
+		thread_current = neko.Lib.load("std", "thread_current", 0);
+		thread_send = neko.Lib.load("std", "thread_send", 2);
+		thread_read_message = neko.Lib.load("std", "thread_read_message", 1);
+
+		mainThreadHandle = thread_current();
+		mainThread = new HaxeThread(mainThreadHandle);
+		mainThread.events = new EventLoop();
+
+		threads = [];
+		threadsMutex = new Mutex();
+	}
 
 	public var events(default,null):Null<EventLoop>;
 	public var handle:ThreadHandle;

+ 12 - 9
std/python/_std/sys/thread/Thread.hx

@@ -22,6 +22,8 @@
 
 package sys.thread;
 
+import haxe.ds.ObjectMap;
+
 private typedef ThreadImpl = HxThread;
 
 abstract Thread(ThreadImpl) from ThreadImpl {
@@ -57,11 +59,6 @@ abstract Thread(ThreadImpl) from ThreadImpl {
 		return this.events;
 	}
 
-	@:keep
-	static function initEventLoop() {
-		@:privateAccess HxThread.current().events = new EventLoop();
-	}
-
 	@:keep
 	static public function processEvents() {
 		HxThread.current().events.loop();
@@ -74,9 +71,16 @@ private class HxThread {
 	final nativeThread:NativeThread;
 	final messages = new Deque<Dynamic>();
 
-	static var threads = new haxe.ds.ObjectMap<NativeThread, HxThread>();
-	static var threadsMutex: Mutex = new Mutex();
-	static var mainThread: HxThread;
+	static var threads:ObjectMap<NativeThread, HxThread>;
+	static var threadsMutex:Mutex;
+	static var mainThread:HxThread;
+
+	static function __init__() {
+		threads = new ObjectMap();
+		threadsMutex = new Mutex();
+		mainThread = new HxThread(PyThreadingAPI.current_thread());
+		mainThread.events = new EventLoop();
+	}
 
 	private function new(t:NativeThread) {
 		nativeThread = t;
@@ -90,7 +94,6 @@ private class HxThread {
 		threadsMutex.acquire();
 		var ct = PyThreadingAPI.current_thread();
 		if (ct == PyThreadingAPI.main_thread()) {
-			if (mainThread == null) mainThread = new HxThread(ct);
 			threadsMutex.release();
 			return mainThread;
 		}

+ 0 - 5
std/sys/thread/Thread.hx

@@ -76,11 +76,6 @@ extern abstract Thread(ThreadImpl) from ThreadImpl {
 	**/
 	public static function readMessage(block:Bool):Dynamic;
 
-	/**
-		Initialize event loop in this thread
-	**/
-	private static function initEventLoop():Void;
-
 	/**
 		Run event loop of the current thread
 	**/

+ 25 - 0
tests/threads/src/cases/TestMainLoop.hx

@@ -5,6 +5,31 @@ import haxe.MainLoop;
 @:timeout(10000)
 @:depends(cases.TestEvents)
 class TestMainLoop extends utest.Test {
+	@:keep static var init = MainLoop.add(() -> {
+		staticInit = true;
+		init.stop();
+	});
+	static var staticInit = false;
+
+	function testWorksInStaticInits_issue10114(async:Async) {
+		var mainThread = Thread.current();
+		var checkAttempts = 3;
+		function check() {
+			checkAttempts++;
+			if(staticInit) {
+				pass();
+				async.done();
+			} else if(checkAttempts > 0) {
+				checkAttempts--;
+				mainThread.events.run(check);
+			} else {
+				fail();
+				async.done();
+			}
+		}
+		mainThread.events.run(check);
+	}
+
 	function testNewAction_immediately(async:Async) {
 		var e1:MainEvent = null;
 		e1 = MainLoop.add(() -> {