Переглянути джерело

[std] Move target.vm.Thread (and friends) to sys.thread.Thread (#7999)

* [std] move all thread classes to sys.thread

* [neko] add @:coreApi

* [cpp] add @:coreApi

* [java] add @:coreApi

* [std] purge redundant documentation

* [std] document Deque and Lock

* [tests] fix java.vm leftovers

* [std] add deprecation typedefs

* [std] fix Tls

* [std] fix Deque

* [typer] error if we access sys.thread on non-threaded target

* [std] nobody saw that
Simon Krajewski 6 роки тому
батько
коміт
320fff2969
56 змінених файлів з 1295 додано та 834 видалено
  1. 2 0
      extra/ImportAll.hx
  2. 1 0
      src/context/common.ml
  3. 5 5
      src/macro/eval/evalHash.ml
  4. 16 16
      src/macro/eval/evalStdLib.ml
  5. 1 0
      src/typing/typeload.ml
  6. 40 0
      std/cpp/_std/sys/thread/Deque.hx
  7. 37 0
      std/cpp/_std/sys/thread/Lock.hx
  8. 41 0
      std/cpp/_std/sys/thread/Mutex.hx
  9. 56 0
      std/cpp/_std/sys/thread/Thread.hx
  10. 45 0
      std/cpp/_std/sys/thread/Tls.hx
  11. 1 17
      std/cpp/vm/Deque.hx
  12. 1 14
      std/cpp/vm/Lock.hx
  13. 1 17
      std/cpp/vm/Mutex.hx
  14. 1 47
      std/cpp/vm/Thread.hx
  15. 1 21
      std/cpp/vm/Tls.hx
  16. 1 1
      std/eval/_std/sys/thread/Thread.hx
  17. 0 8
      std/eval/vm/Deque.hx
  18. 0 7
      std/eval/vm/Lock.hx
  19. 0 8
      std/eval/vm/Mutex.hx
  20. 0 6
      std/eval/vm/Tls.hx
  21. 6 6
      std/haxe/EntryPoint.hx
  22. 4 4
      std/haxe/io/FPHelper.hx
  23. 1 1
      std/hl/_std/sys/thread/Deque.hx
  24. 7 7
      std/hl/_std/sys/thread/Mutex.hx
  25. 1 1
      std/hl/_std/sys/thread/Thread.hx
  26. 3 3
      std/hl/_std/sys/thread/Tls.hx
  27. 92 0
      std/java/_std/sys/thread/Deque.hx
  28. 95 0
      std/java/_std/sys/thread/Lock.hx
  29. 49 0
      std/java/_std/sys/thread/Mutex.hx
  30. 112 0
      std/java/_std/sys/thread/Thread.hx
  31. 46 0
      std/java/_std/sys/thread/Tls.hx
  32. 2 72
      std/java/vm/Deque.hx
  33. 2 83
      std/java/vm/Lock.hx
  34. 2 40
      std/java/vm/Mutex.hx
  35. 2 89
      std/java/vm/Thread.hx
  36. 2 26
      std/java/vm/Tls.hx
  37. 48 0
      std/neko/_std/sys/thread/Deque.hx
  38. 43 0
      std/neko/_std/sys/thread/Lock.hx
  39. 48 0
      std/neko/_std/sys/thread/Mutex.hx
  40. 122 0
      std/neko/_std/sys/thread/Thread.hx
  41. 46 0
      std/neko/_std/sys/thread/Tls.hx
  42. 1 40
      std/neko/vm/Deque.hx
  43. 1 32
      std/neko/vm/Lock.hx
  44. 1 46
      std/neko/vm/Mutex.hx
  45. 1 113
      std/neko/vm/Thread.hx
  46. 1 37
      std/neko/vm/Tls.hx
  47. 59 0
      std/sys/thread/Deque.hx
  48. 80 0
      std/sys/thread/Lock.hx
  49. 59 0
      std/sys/thread/Mutex.hx
  50. 50 0
      std/sys/thread/Thread.hx
  51. 42 0
      std/sys/thread/Tls.hx
  52. 5 31
      tests/threads/src/import.hx
  53. 5 25
      tests/unit/src/unit/TestThreads.hx
  54. 3 3
      tests/unit/src/unit/issues/Issue3084.hx
  55. 2 6
      tests/unit/src/unit/issues/Issue3767.hx
  56. 2 2
      tests/unit/src/unit/issues/Issue4878.hx

+ 2 - 0
extra/ImportAll.hx

@@ -52,6 +52,8 @@ class ImportAll {
 			return;
 			return;
 		case "sys":
 		case "sys":
 			if(!isSysTarget()) return;
 			if(!isSysTarget()) return;
+		case "sys.thread":
+			if ( !Context.defined("target.threaded") ) return;
 		case "java":
 		case "java":
 			if( !Context.defined("java") ) return;
 			if( !Context.defined("java") ) return;
 		case "cs":
 		case "cs":

+ 1 - 0
src/context/common.ml

@@ -370,6 +370,7 @@ let get_config com =
 			default_config with
 			default_config with
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
+			pf_supports_threads = true;
 		}
 		}
 	| Eval ->
 	| Eval ->
 		{
 		{

+ 5 - 5
src/macro/eval/evalHash.ml

@@ -116,13 +116,13 @@ let key_socket = hash "socket"
 let key_read = hash "read"
 let key_read = hash "read"
 let key_write = hash "write"
 let key_write = hash "write"
 let key_others = hash "others"
 let key_others = hash "others"
-let key_eval_vm_Thread = hash "eval.vm.Thread"
+let key_sys_net_Thread = hash "sys.thread.Thread"
 let key_haxe_zip_Compress = hash "haxe.zip.Compress"
 let key_haxe_zip_Compress = hash "haxe.zip.Compress"
 let key_haxe_zip_Uncompress = hash "haxe.zip.Uncompress"
 let key_haxe_zip_Uncompress = hash "haxe.zip.Uncompress"
 let key_done = hash "done"
 let key_done = hash "done"
 let key_eval_toplevel = hash "eval-toplevel"
 let key_eval_toplevel = hash "eval-toplevel"
 let key_haxe_iterators_map_key_value_iterator = hash "haxe.iterators.MapKeyValueIterator"
 let key_haxe_iterators_map_key_value_iterator = hash "haxe.iterators.MapKeyValueIterator"
-let key_eval_vm_Mutex = hash "eval.vm.Mutex"
-let key_eval_vm_Lock = hash "eval.vm.Lock"
-let key_eval_vm_Tls = hash "eval.vm.Tls"
-let key_eval_vm_Deque = hash "eval.vm.Deque"
+let key_sys_net_Mutex = hash "sys.thread.Mutex"
+let key_sys_net_Lock = hash "sys.thread.Lock"
+let key_sys_net_Tls = hash "sys.thread.Tls"
+let key_sys_net_Deque = hash "sys.thread.Deque"

+ 16 - 16
src/macro/eval/evalStdLib.ml

@@ -2667,7 +2667,7 @@ module StdThread = struct
 
 
 	let self = vfun0 (fun () ->
 	let self = vfun0 (fun () ->
 		let eval = get_eval (get_ctx()) in
 		let eval = get_eval (get_ctx()) in
-		encode_instance key_eval_vm_Thread ~kind:(IThread eval.thread)
+		encode_instance key_sys_net_Thread ~kind:(IThread eval.thread)
 	)
 	)
 
 
 	let readMessage = vfun1 (fun blocking ->
 	let readMessage = vfun1 (fun blocking ->
@@ -3163,7 +3163,7 @@ let init_constructors builtins =
 				encode_instance key_haxe_zip_Uncompress ~kind:(IZip { z = z; z_flush = Extc.Z_NO_FLUSH })
 				encode_instance key_haxe_zip_Uncompress ~kind:(IZip { z = z; z_flush = Extc.Z_NO_FLUSH })
 			| _ -> assert false
 			| _ -> assert false
 		);
 		);
-	add key_eval_vm_Thread
+	add key_sys_net_Thread
 		(fun vl -> match vl with
 		(fun vl -> match vl with
 			| [f] ->
 			| [f] ->
 				let ctx = get_ctx() in
 				let ctx = get_ctx() in
@@ -3210,33 +3210,33 @@ let init_constructors builtins =
 					tdeque = Deque.create();
 					tdeque = Deque.create();
 				} in
 				} in
 				thread.tthread <- Thread.create f thread;
 				thread.tthread <- Thread.create f thread;
-				encode_instance key_eval_vm_Thread ~kind:(IThread thread)
+				encode_instance key_sys_net_Thread ~kind:(IThread thread)
 			| _ -> assert false
 			| _ -> assert false
 		);
 		);
-	add key_eval_vm_Mutex
+	add key_sys_net_Mutex
 		(fun _ ->
 		(fun _ ->
 			let mutex = {
 			let mutex = {
 				mmutex = Mutex.create();
 				mmutex = Mutex.create();
 				mowner = None;
 				mowner = None;
 			} in
 			} in
-			encode_instance key_eval_vm_Mutex ~kind:(IMutex mutex)
+			encode_instance key_sys_net_Mutex ~kind:(IMutex mutex)
 		);
 		);
-	add key_eval_vm_Lock
+	add key_sys_net_Lock
 		(fun _ ->
 		(fun _ ->
 			let lock = {
 			let lock = {
 				ldeque = Deque.create();
 				ldeque = Deque.create();
 			} in
 			} in
-			encode_instance key_eval_vm_Lock ~kind:(ILock lock)
+			encode_instance key_sys_net_Lock ~kind:(ILock lock)
 		);
 		);
 	let tls_counter = ref (-1) in
 	let tls_counter = ref (-1) in
-	add key_eval_vm_Tls
+	add key_sys_net_Tls
 		(fun _ ->
 		(fun _ ->
 			incr tls_counter;
 			incr tls_counter;
-			encode_instance key_eval_vm_Tls ~kind:(ITls !tls_counter)
+			encode_instance key_sys_net_Tls ~kind:(ITls !tls_counter)
 		);
 		);
-	add key_eval_vm_Deque
+	add key_sys_net_Deque
 		(fun _ ->
 		(fun _ ->
-			encode_instance key_eval_vm_Deque ~kind:(IDeque (Deque.create()))
+			encode_instance key_sys_net_Deque ~kind:(IDeque (Deque.create()))
 		)
 		)
 
 
 let init_empty_constructors builtins =
 let init_empty_constructors builtins =
@@ -3362,7 +3362,7 @@ let init_standard_library builtins =
 		"getTime",StdDate.getTime;
 		"getTime",StdDate.getTime;
 		"toString",StdDate.toString;
 		"toString",StdDate.toString;
 	];
 	];
-	init_fields builtins (["eval";"vm"],"Deque") [] [
+	init_fields builtins (["sys";"thread"],"Deque") [] [
 		"add",StdDeque.add;
 		"add",StdDeque.add;
 		"push",StdDeque.push;
 		"push",StdDeque.push;
 		"pop",StdDeque.pop;
 		"pop",StdDeque.pop;
@@ -3445,7 +3445,7 @@ let init_standard_library builtins =
 		"hostToString",StdHost.hostToString;
 		"hostToString",StdHost.hostToString;
 		"resolve",StdHost.resolve;
 		"resolve",StdHost.resolve;
 	] [];
 	] [];
-	init_fields builtins (["eval";"vm"],"Lock") [] [
+	init_fields builtins (["sys";"thread"],"Lock") [] [
 		"release",StdLock.release;
 		"release",StdLock.release;
 		"wait",StdLock.wait;
 		"wait",StdLock.wait;
 	];
 	];
@@ -3485,7 +3485,7 @@ let init_standard_library builtins =
 		"encode",StdMd5.encode;
 		"encode",StdMd5.encode;
 		"make",StdMd5.make;
 		"make",StdMd5.make;
 	] [];
 	] [];
-	init_fields builtins (["eval";"vm"],"Mutex") [] [
+	init_fields builtins (["sys";"thread"],"Mutex") [] [
 		"acquire",StdMutex.acquire;
 		"acquire",StdMutex.acquire;
 		"tryAcquire",StdMutex.tryAcquire;
 		"tryAcquire",StdMutex.tryAcquire;
 		"release",StdMutex.release;
 		"release",StdMutex.release;
@@ -3604,7 +3604,7 @@ let init_standard_library builtins =
 		"systemName",StdSys.systemName;
 		"systemName",StdSys.systemName;
 		"time",StdSys.time;
 		"time",StdSys.time;
 	] [];
 	] [];
-	init_fields builtins (["eval";"vm"],"Thread") [
+	init_fields builtins (["sys";"thread"],"Thread") [
 		"delay",StdThread.delay;
 		"delay",StdThread.delay;
 		"exit",StdThread.exit;
 		"exit",StdThread.exit;
 		"join",StdThread.join;
 		"join",StdThread.join;
@@ -3616,7 +3616,7 @@ let init_standard_library builtins =
 		"kill",StdThread.kill;
 		"kill",StdThread.kill;
 		"sendMessage",StdThread.sendMessage;
 		"sendMessage",StdThread.sendMessage;
 	];
 	];
-	init_fields builtins (["eval";"vm"],"Tls") [] [
+	init_fields builtins (["sys";"thread"],"Tls") [] [
 		"get_value",StdTls.get_value;
 		"get_value",StdTls.get_value;
 		"set_value",StdTls.set_value;
 		"set_value",StdTls.set_value;
 	];
 	];

+ 1 - 0
src/typing/typeload.ml

@@ -733,6 +733,7 @@ let load_core_class ctx c =
 			com2.defines.Define.values <- PMap.empty;
 			com2.defines.Define.values <- PMap.empty;
 			Common.define com2 Define.CoreApi;
 			Common.define com2 Define.CoreApi;
 			Common.define com2 Define.Sys;
 			Common.define com2 Define.Sys;
+			Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
 			if ctx.in_macro then Common.define com2 Define.Macro;
 			if ctx.in_macro then Common.define com2 Define.Macro;
 			com2.class_path <- ctx.com.std_path;
 			com2.class_path <- ctx.com.std_path;
 			if com2.display.dms_check_core_api then com2.display <- {com2.display with dms_check_core_api = false};
 			if com2.display.dms_check_core_api then com2.display <- {com2.display with dms_check_core_api = false};

+ 40 - 0
std/cpp/_std/sys/thread/Deque.hx

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Deque<T> {
+	var q : Dynamic;
+	public function new() {
+		q = untyped __global__.__hxcpp_deque_create();
+	}
+	public function add( i : T ):Void {
+		untyped __global__.__hxcpp_deque_add(q,i);
+	}
+	public function push( i : T ):Void {
+		untyped __global__.__hxcpp_deque_push(q,i);
+	}
+	public function pop( block : Bool ) : Null<T> {
+		return untyped __global__.__hxcpp_deque_pop(q,block);
+	}
+}
+

+ 37 - 0
std/cpp/_std/sys/thread/Lock.hx

@@ -0,0 +1,37 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Lock {
+	var l : Dynamic;
+	public function new() {
+		l = untyped __global__.__hxcpp_lock_create();
+	}
+	public function wait( ?timeout : Float = -1) : Bool {
+		return untyped __global__.__hxcpp_lock_wait(l,timeout);
+	}
+	public function release():Void {
+		untyped __global__.__hxcpp_lock_release(l);
+	}
+}
+

+ 41 - 0
std/cpp/_std/sys/thread/Mutex.hx

@@ -0,0 +1,41 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Mutex {
+	var m : Dynamic;
+
+	public function new() {
+		m = untyped __global__.__hxcpp_mutex_create();
+	}
+	public function acquire():Void {
+		untyped __global__.__hxcpp_mutex_acquire(m);
+	}
+	public function tryAcquire() : Bool {
+		return untyped __global__.__hxcpp_mutex_try(m);
+	}
+	public function release():Void {
+		untyped __global__.__hxcpp_mutex_release(m);
+	}
+}
+

+ 56 - 0
std/cpp/_std/sys/thread/Thread.hx

@@ -0,0 +1,56 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+typedef ThreadHandle = Dynamic;
+
+@:coreApi
+class Thread {
+
+	var handle(default,null) : ThreadHandle;
+
+	function new(h:ThreadHandle):Void {
+		handle = h;
+	}
+
+	public function sendMessage( msg : Dynamic ):Void {
+		untyped __global__.__hxcpp_thread_send(handle,msg);
+	}
+
+	public static function current():Thread {
+		return new Thread(untyped __global__.__hxcpp_thread_current());
+	}
+
+	public static function create( callb : Void -> Void ):Thread {
+		return new Thread(untyped __global__.__hxcpp_thread_create(callb));
+	}
+
+	public static function readMessage( block : Bool ) : Dynamic {
+		return untyped __global__.__hxcpp_thread_read_message(block);
+	}
+
+	@:keep function __compare(t:Thread) : Int {
+		return handle == t.handle ? 0 : 1;
+	}
+
+}
+

+ 45 - 0
std/cpp/_std/sys/thread/Tls.hx

@@ -0,0 +1,45 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Tls<T> {
+
+	static var sFreeSlot = 0;
+	var mTLSID : Int;
+	public var value(get,set) : T;
+
+	public function new() {
+		mTLSID = sFreeSlot++;
+	}
+
+	function get_value() : T {
+		return untyped __global__.__hxcpp_tls_get(mTLSID);
+	}
+
+	function set_value( v : T ):T {
+		untyped __global__.__hxcpp_tls_set(mTLSID,v);
+		return v;
+	}
+
+}
+

+ 1 - 17
std/cpp/vm/Deque.hx

@@ -21,20 +21,4 @@
  */
  */
 package cpp.vm;
 package cpp.vm;
 
 
-
-class Deque<T> {
-	var q : Dynamic;
-	public function new() {
-		q = untyped __global__.__hxcpp_deque_create();
-	}
-	public function add( i : T ) {
-		untyped __global__.__hxcpp_deque_add(q,i);
-	}
-	public function push( i : T ) {
-		untyped __global__.__hxcpp_deque_push(q,i);
-	}
-	public function pop( block : Bool ) : Null<T> {
-		return untyped __global__.__hxcpp_deque_pop(q,block);
-	}
-}
-
+@:deprecated typedef Deque<T> = sys.thread.Deque<T>;

+ 1 - 14
std/cpp/vm/Lock.hx

@@ -21,17 +21,4 @@
  */
  */
 package cpp.vm;
 package cpp.vm;
 
 
-
-class Lock {
-	var l : Dynamic;
-	public function new() {
-		l = untyped __global__.__hxcpp_lock_create();
-	}
-	public function wait( ?timeout : Float = -1) : Bool {
-		return untyped __global__.__hxcpp_lock_wait(l,timeout);
-	}
-	public function release() {
-		untyped __global__.__hxcpp_lock_release(l);
-	}
-}
-
+@:deprecated typedef Lock = sys.thread.Lock;

+ 1 - 17
std/cpp/vm/Mutex.hx

@@ -21,20 +21,4 @@
  */
  */
 package cpp.vm;
 package cpp.vm;
 
 
-class Mutex {
-	var m : Dynamic;
-
-	public function new() {
-		m = untyped __global__.__hxcpp_mutex_create();
-	}
-	public function acquire() {
-		untyped __global__.__hxcpp_mutex_acquire(m);
-	}
-	public function tryAcquire() : Bool {
-		return untyped __global__.__hxcpp_mutex_try(m);
-	}
-	public function release() {
-		untyped __global__.__hxcpp_mutex_release(m);
-	}
-}
-
+@:deprecated typedef Mutex = sys.thread.Mutex;

+ 1 - 47
std/cpp/vm/Thread.hx

@@ -21,50 +21,4 @@
  */
  */
 package cpp.vm;
 package cpp.vm;
 
 
-typedef ThreadHandle = Dynamic;
-
-class Thread {
-
-	public var handle(default,null) : ThreadHandle;
-
-	function new(h) {
-		handle = h;
-	}
-
-	/**
-		Send a message to the thread queue. This message can be read by using `readMessage`.
-	**/
-	public function sendMessage( msg : Dynamic ) {
-		untyped __global__.__hxcpp_thread_send(handle,msg);
-	}
-
-
-	/**
-		Returns the current thread.
-	**/
-	public static function current() {
-		return new Thread(untyped __global__.__hxcpp_thread_current());
-	}
-
-	/**
-		Creates a new thread that will execute the `callb` function, then exit.
-	**/
-	public static function create( callb : Void -> Void ) {
-		return new Thread(untyped __global__.__hxcpp_thread_create(callb));
-	}
-
-	/**
-		Reads a message from the thread queue. If `block` is true, the function
-		blocks until a message is available. If `block` is false, the function
-		returns `null` if no message is available.
-	**/
-	public static function readMessage( block : Bool ) : Dynamic {
-		return untyped __global__.__hxcpp_thread_read_message(block);
-	}
-
-	@:keep function __compare(t:Thread) : Int {
-		return handle == t.handle ? 0 : 1;
-	}
-
-}
-
+@:deprecated typedef Thread = sys.thread.Thread;

+ 1 - 21
std/cpp/vm/Tls.hx

@@ -21,24 +21,4 @@
  */
  */
 package cpp.vm;
 package cpp.vm;
 
 
-class Tls<T> {
-
-	static var sFreeSlot = 0;
-	var mTLSID : Int;
-	public var value(get,set) : T;
-
-	public function new() {
-		mTLSID = sFreeSlot++;
-	}
-
-	function get_value() : T {
-		return untyped __global__.__hxcpp_tls_get(mTLSID);
-	}
-
-	function set_value( v : T ) {
-		untyped __global__.__hxcpp_tls_set(mTLSID,v);
-		return v;
-	}
-
-}
-
+@:deprecated typedef Tls<T> = sys.thread.Tls<T>;

+ 1 - 1
std/eval/vm/Thread.hx → std/eval/_std/sys/thread/Thread.hx

@@ -20,7 +20,7 @@
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
 
 
-package eval.vm;
+package sys.thread;
 
 
 /**
 /**
 	Experimental Thread API.
 	Experimental Thread API.

+ 0 - 8
std/eval/vm/Deque.hx

@@ -1,8 +0,0 @@
-package eval.vm;
-
-extern class Deque<T> {
-	function new():Void;
-	function add(i:T):Void;
-	function pop(block:Bool):Null<T>;
-	function push(i:T):Void;
-}

+ 0 - 7
std/eval/vm/Lock.hx

@@ -1,7 +0,0 @@
-package eval.vm;
-
-extern class Lock {
-	function new():Void;
-	function release():Void;
-	function wait(?timeout:Float):Bool;
-}

+ 0 - 8
std/eval/vm/Mutex.hx

@@ -1,8 +0,0 @@
-package eval.vm;
-
-extern class Mutex {
-	function new():Void;
-	function acquire():Void;
-	function tryAcquire():Bool;
-	function release():Void;
-}

+ 0 - 6
std/eval/vm/Tls.hx

@@ -1,6 +0,0 @@
-package eval.vm;
-
-extern class Tls<T> {
-	public var value(get, set):T;
-	function new():Void;
-}

+ 6 - 6
std/haxe/EntryPoint.hx

@@ -1,13 +1,13 @@
 package haxe;
 package haxe;
 
 
 #if (neko && !macro && !interp)
 #if (neko && !macro && !interp)
-import neko.vm.Lock;
-import neko.vm.Mutex;
-import neko.vm.Thread;
+import sys.thread.Lock;
+import sys.thread.Mutex;
+import sys.thread.Thread;
 #elseif cpp
 #elseif cpp
-import cpp.vm.Lock;
-import cpp.vm.Mutex;
-import cpp.vm.Thread;
+import sys.thread.Lock;
+import sys.thread.Mutex;
+import sys.thread.Thread;
 #elseif java
 #elseif java
 import java.vm.Lock;
 import java.vm.Lock;
 import java.vm.Mutex;
 import java.vm.Mutex;

+ 4 - 4
std/haxe/io/FPHelper.hx

@@ -30,7 +30,7 @@ class FPHelper {
 	#if neko_v21
 	#if neko_v21
 	// stored in helper
 	// stored in helper
 	#elseif neko
 	#elseif neko
-	static var i64tmp = new neko.vm.Tls<Int64>();
+	static var i64tmp = new sys.thread.Tls<Int64>();
 	#elseif !(java || cs || cpp)
 	#elseif !(java || cs || cpp)
 	static var i64tmp = Int64.ofInt(0);
 	static var i64tmp = Int64.ofInt(0);
 
 
@@ -111,10 +111,10 @@ class FPHelper {
 
 
 	#if neko
 	#if neko
 		#if neko_v21
 		#if neko_v21
-		static var helpers = new neko.vm.Tls<neko.NativeArray<Dynamic>>();
+		static var helpers = new sys.thread.Tls<neko.NativeArray<Dynamic>>();
 		#else
 		#else
-		static var helperf = new neko.vm.Tls<neko.NativeString>();
-		static var helperd = new neko.vm.Tls<neko.NativeString>();
+		static var helperf = new sys.thread.Tls<neko.NativeString>();
+		static var helperd = new sys.thread.Tls<neko.NativeString>();
 		static var _float_of_bytes = neko.Lib.load("std","float_of_bytes",2);
 		static var _float_of_bytes = neko.Lib.load("std","float_of_bytes",2);
 		static var _double_of_bytes = neko.Lib.load("std","double_of_bytes",2);
 		static var _double_of_bytes = neko.Lib.load("std","double_of_bytes",2);
 		static var _float_bytes = neko.Lib.load("std","float_bytes",2);
 		static var _float_bytes = neko.Lib.load("std","float_bytes",2);

+ 1 - 1
std/hl/vm/Deque.hx → std/hl/_std/sys/thread/Deque.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
-package hl.vm;
+package sys.thread;
 
 
 /**
 /**
 	A message queue for multithread access.
 	A message queue for multithread access.

+ 7 - 7
std/hl/vm/Mutex.hx → std/hl/_std/sys/thread/Mutex.hx

@@ -19,11 +19,11 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
-package hl.vm;
+package sys.thread;
 
 
 /**
 /**
-	Creates a mutex, which can be used to acquire a temporary lock 
-	to access some ressource. The main difference with a lock is 
+	Creates a mutex, which can be used to acquire a temporary lock
+	to access some ressource. The main difference with a lock is
 	that a mutex must always be released by the owner thread.
 	that a mutex must always be released by the owner thread.
 **/
 **/
 abstract Mutex(hl.Abstract<"hl_mutex">) {
 abstract Mutex(hl.Abstract<"hl_mutex">) {
@@ -37,14 +37,14 @@ abstract Mutex(hl.Abstract<"hl_mutex">) {
 
 
 	/**
 	/**
 		The current thread acquire the mutex or wait if not available.
 		The current thread acquire the mutex or wait if not available.
-		The same thread can acquire several times the same mutex but 
+		The same thread can acquire several times the same mutex but
 		must release it as many times it has been acquired.
 		must release it as many times it has been acquired.
 	**/
 	**/
 	@:hlNative("std","mutex_acquire") public function acquire() {
 	@:hlNative("std","mutex_acquire") public function acquire() {
 	}
 	}
 
 
 	/**
 	/**
-		Try to acquire the mutex, returns true if acquire or false 
+		Try to acquire the mutex, returns true if acquire or false
 		if it's already locked by another thread.
 		if it's already locked by another thread.
 	**/
 	**/
 	@:hlNative("std","mutex_try_acquire") public function tryAcquire() : Bool {
 	@:hlNative("std","mutex_try_acquire") public function tryAcquire() : Bool {
@@ -52,7 +52,7 @@ abstract Mutex(hl.Abstract<"hl_mutex">) {
 	}
 	}
 
 
 	/**
 	/**
-		Release a mutex that has been acquired by the current thread. 
+		Release a mutex that has been acquired by the current thread.
 		The behavior is undefined if the current thread does not own
 		The behavior is undefined if the current thread does not own
 		the mutex.
 		the mutex.
 	**/
 	**/
@@ -62,5 +62,5 @@ abstract Mutex(hl.Abstract<"hl_mutex">) {
 	@:hlNative("std","mutex_alloc") public static function alloc( b : Bool ) {
 	@:hlNative("std","mutex_alloc") public static function alloc( b : Bool ) {
 		return null;
 		return null;
 	}
 	}
-	
+
 }
 }

+ 1 - 1
std/hl/vm/Thread.hx → std/hl/_std/sys/thread/Thread.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
-package hl.vm;
+package sys.thread;
 
 
 typedef ThreadHandle = hl.Abstract<"hl_thread">;
 typedef ThreadHandle = hl.Abstract<"hl_thread">;
 
 

+ 3 - 3
std/hl/vm/Tls.hx → std/hl/_std/sys/thread/Tls.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
-package hl.vm;
+package sys.thread;
 
 
 /**
 /**
 	Creates thread local storage.
 	Creates thread local storage.
@@ -32,8 +32,8 @@ abstract Tls<T>(hl.Abstract<"hl_tls">) {
 
 
 	/**
 	/**
 		Creates thread local storage. This is placeholder that can store
 		Creates thread local storage. This is placeholder that can store
-		a value that will be different depending on the local thread. 
-		Set the tls value to `null` before exiting the thread 
+		a value that will be different depending on the local thread.
+		Set the tls value to `null` before exiting the thread
 		or the memory will never be collected.
 		or the memory will never be collected.
 	**/
 	**/
 	public function new() {
 	public function new() {

+ 92 - 0
std/java/_std/sys/thread/Deque.hx

@@ -0,0 +1,92 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+import java.Lib;
+
+@:coreApi
+@:native('haxe.java.vm.Deque')
+@:nativeGen class Deque<T>
+{
+	@:private var head:Node<T>;
+	@:private var tail:Node<T>;
+
+	public function new()
+	{
+		this.head = this.tail = new Node(null);
+	}
+
+	public function add(i : T):Void
+	{
+		var n = new Node(i);
+		untyped __lock__(this,
+		{
+			tail.next = n;
+			tail = n;
+			try { untyped this.notify(); } catch(e:Dynamic) { throw e; }
+		});
+	}
+
+	public function push(i : T):Void
+	{
+		var n = new Node(i);
+		untyped __lock__(this,
+		{
+			n.next = head.next;
+			head.next = n;
+			try { untyped this.notify(); } catch(e:Dynamic) { throw e; }
+		});
+	}
+
+	public function pop(block : Bool) : Null<T>
+	{
+		var ret = null;
+		untyped __lock__(this, {
+			var n = null;
+			do {
+				n = head.next;
+				if (n != null)
+				{
+					ret = n.value;
+					n.value = null;
+					head = n;
+				} else if (block) {
+					//block
+					try { untyped this.wait(); } catch(e:Dynamic) { throw e; }
+				}
+			} while( block && n == null );
+		});
+		return ret;
+	}
+}
+
+@:native('haxe.java.vm.DequeNode')
+@:nativeGen
+class Node<T>
+{
+	public var value:T;
+	public var next:Node<T>;
+
+	public function new(val)
+	{
+		this.value = val;
+	}
+}

+ 95 - 0
std/java/_std/sys/thread/Lock.hx

@@ -0,0 +1,95 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+import java.Lib;
+import java.lang.System;
+using haxe.Int64;
+
+@:coreApi
+@:native('haxe.java.vm.Lock') class Lock
+{
+	@:private @:volatile var releasedCount = 0;
+
+	public function new()
+	{
+	}
+
+	public function wait(?timeout : Float) : Bool
+	{
+		var ret = false;
+		java.Lib.lock(this,
+		{
+			if (--releasedCount < 0)
+			{
+				if (timeout == null)
+				{
+					// since .notify() is asynchronous, this `while` is needed
+					// because there is a very remote possibility of release() awaking a thread,
+					// but before it releases, another thread calls wait - and since the release count
+					// is still positive, it will get the lock.
+					while( releasedCount < 0 )
+					{
+						try
+						{
+							untyped __java__("this.wait()");
+						}
+						catch(e:java.lang.InterruptedException)
+						{
+						}
+					}
+				} else {
+					var timeout:haxe.Int64 = cast timeout * 1000;
+					var cur = System.currentTimeMillis(),
+					    max = cur.add(timeout);
+					// see above comment about this while loop
+					while ( releasedCount < 0 && cur.compare(max) < 0 )
+					{
+						try
+						{
+							var t = max.sub(cur);
+							untyped __java__("this.wait({0})",t);
+							cur = System.currentTimeMillis();
+						}
+						catch(e:java.lang.InterruptedException)
+						{
+						}
+					}
+				}
+			}
+			ret = this.releasedCount >= 0;
+			if (!ret)
+				this.releasedCount++; //timed out
+		});
+		return ret;
+	}
+
+	public function release():Void
+	{
+		untyped __lock__(this,
+		{
+			if (++releasedCount >= 0)
+			{
+				untyped this.notify();
+			}
+		});
+	}
+}

+ 49 - 0
std/java/_std/sys/thread/Mutex.hx

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+import java.util.concurrent.locks.ReentrantLock;
+
+@:coreApi
+@:native('haxe.java.vm.Mutex') class Mutex
+{
+	@:private var lock:ReentrantLock;
+
+	public function new()
+	{
+		this.lock = new ReentrantLock();
+	}
+
+	public function tryAcquire():Bool
+	{
+		return this.lock.tryLock();
+	}
+
+	public function acquire():Void
+	{
+		this.lock.lock();
+	}
+
+	public function release():Void
+	{
+		this.lock.unlock();
+	}
+}

+ 112 - 0
std/java/_std/sys/thread/Thread.hx

@@ -0,0 +1,112 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+import java.Lib;
+
+@:coreApi
+@:native('haxe.java.vm.Thread') class Thread
+{
+
+	@:private static var javaThreadToHaxe = new haxe.ds.WeakMap<java.lang.Thread, sys.thread.Thread>();
+	@:private static var mainJavaThread = java.lang.Thread.currentThread();
+	@:private static var mainHaxeThread = {
+		var ret = new Thread();
+		javaThreadToHaxe.set(mainJavaThread, ret);
+		ret;
+	};
+
+
+	private static function getThread(jt:java.lang.Thread):Thread
+	{
+		if (Std.is(jt, HaxeThread))
+		{
+			var t:HaxeThread = cast jt;
+			return t.threadObject;
+		}
+		else if (jt == mainJavaThread)
+		{
+			return mainHaxeThread;
+		}
+		else
+		{
+			var ret = null;
+			untyped __lock__(javaThreadToHaxe, {
+				ret = javaThreadToHaxe.get(jt);
+				if (ret == null)
+				{
+					ret = new Thread();
+					javaThreadToHaxe.set(jt, ret);
+				}
+
+			});
+			return ret;
+		}
+	}
+
+	private var messages:Deque<Dynamic>;
+
+  function new()
+	{
+		this.messages = new Deque();
+	}
+
+	public function sendMessage(msg:Dynamic):Void
+	{
+		messages.add(msg);
+	}
+
+	public static function current():Thread
+	{
+		return getThread( java.lang.Thread.currentThread() );
+	}
+
+	public static function readMessage(block : Bool) : Dynamic
+	{
+		return current().messages.pop(block);
+	}
+
+	public static function create(callb:Void->Void):Thread
+	{
+		var ret = new Thread();
+		var t = new HaxeThread(ret, callb);
+		t.start();
+		return ret;
+	}
+}
+
+@:native('haxe.java.vm.HaxeThread')
+private class HaxeThread extends java.lang.Thread
+{
+	public var threadObject(default, null):Thread;
+	private var runFunction:Void->Void;
+	@:overload override public function run():Void
+	{
+		runFunction();
+	}
+	public function new(hxThread:Thread, run:Void->Void)
+	{
+		super();
+		threadObject = hxThread;
+		runFunction = run;
+		setDaemon(true);
+	}
+}

+ 46 - 0
std/java/_std/sys/thread/Tls.hx

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+// @:coreApi // causes some overload error...
+@:native('haxe.java.vm.Tls') class Tls<T>
+{
+	var t : java.lang.ThreadLocal<T>;
+	public var value(get,set):T;
+
+	public function new()
+	{
+		this.t = new java.lang.ThreadLocal();
+	}
+
+	inline private function get_value():T
+	{
+		return t.get();
+	}
+
+	inline private function set_value(v:T):T
+	{
+		t.set(v);
+		return v;
+	}
+
+}

+ 2 - 72
std/java/vm/Deque.hx

@@ -19,76 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
- package java.vm;
-import java.Lib;
+package java.vm;
 
 
-/**
-	A Lock-free Queue implementation
-**/
-@:native('haxe.java.vm.Deque')
-@:nativeGen class Deque<T>
-{
-	@:private var head:Node<T>;
-	@:private var tail:Node<T>;
-
-	public function new()
-	{
-		this.head = this.tail = new Node(null);
-	}
-
-	public function add(i : T)
-	{
-		var n = new Node(i);
-		untyped __lock__(this,
-		{
-			tail.next = n;
-			tail = n;
-			try { untyped this.notify(); } catch(e:Dynamic) { throw e; }
-		});
-	}
-
-	public function push(i : T)
-	{
-		var n = new Node(i);
-		untyped __lock__(this,
-		{
-			n.next = head.next;
-			head.next = n;
-			try { untyped this.notify(); } catch(e:Dynamic) { throw e; }
-		});
-	}
-
-	public function pop(block : Bool) : Null<T>
-	{
-		var ret = null;
-		untyped __lock__(this, {
-			var n = null;
-			do {
-				n = head.next;
-				if (n != null)
-				{
-					ret = n.value;
-					n.value = null;
-					head = n;
-				} else if (block) {
-					//block
-					try { untyped this.wait(); } catch(e:Dynamic) { throw e; }
-				}
-			} while( block && n == null );
-		});
-		return ret;
-	}
-}
-
-@:native('haxe.java.vm.DequeNode')
-@:nativeGen
-class Node<T>
-{
-	public var value:T;
-	public var next:Node<T>;
-
-	public function new(val)
-	{
-		this.value = val;
-	}
-}
+@:deprecated typedef Deque<T> = sys.thread.Deque<T>;

+ 2 - 83
std/java/vm/Lock.hx

@@ -19,87 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
- package java.vm;
-import java.Lib;
-import java.lang.System;
-using haxe.Int64;
+package java.vm;
 
 
-@:native('haxe.java.vm.Lock') class Lock
-{
-	@:private @:volatile var releasedCount = 0;
-
-	/**
-		Creates a new lock, which is initially locked
-	**/
-	public function new()
-	{
-	}
-
-	/**
-		Waits for a lock to be released and acquire it.
-		If `timeout` (in seconds) is not null and expires then the returned value is false
-	**/
-	public function wait(?timeout : Float) : Bool
-	{
-		var ret = false;
-		java.Lib.lock(this,
-		{
-			if (--releasedCount < 0)
-			{
-				if (timeout == null)
-				{
-					// since .notify() is asynchronous, this `while` is needed
-					// because there is a very remote possibility of release() awaking a thread,
-					// but before it releases, another thread calls wait - and since the release count
-					// is still positive, it will get the lock.
-					while( releasedCount < 0 )
-					{
-						try
-						{
-							untyped __java__("this.wait()");
-						}
-						catch(e:java.lang.InterruptedException)
-						{
-						}
-					}
-				} else {
-					var timeout:haxe.Int64 = cast timeout * 1000;
-					var cur = System.currentTimeMillis(),
-					    max = cur.add(timeout);
-					// see above comment about this while loop
-					while ( releasedCount < 0 && cur.compare(max) < 0 )
-					{
-						try
-						{
-							var t = max.sub(cur);
-							untyped __java__("this.wait({0})",t);
-							cur = System.currentTimeMillis();
-						}
-						catch(e:java.lang.InterruptedException)
-						{
-						}
-					}
-				}
-			}
-			ret = this.releasedCount >= 0;
-			if (!ret)
-				this.releasedCount++; //timed out
-		});
-		return ret;
-	}
-
-	/**
-		Release a lock. The thread does not need to own the lock to be able to release it.
-		If a lock is released several times, it can be acquired as many times
-	**/
-	public function release()
-	{
-		untyped __lock__(this,
-		{
-			if (++releasedCount >= 0)
-			{
-				untyped this.notify();
-			}
-		});
-	}
-}
+@:deprecated typedef Lock = sys.thread.Lock;

+ 2 - 40
std/java/vm/Mutex.hx

@@ -19,44 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
- package java.vm;
-import java.util.concurrent.locks.ReentrantLock;
+package java.vm;
 
 
-@:native('haxe.java.vm.Mutex') class Mutex
-{
-	@:private var lock:ReentrantLock;
-
-	/**
-		Creates a mutex, which can be used to acquire a temporary lock to access some resource.
-		The main difference with a lock is that a mutex must always be released by the owner thread
-	**/
-	public function new()
-	{
-		this.lock = new ReentrantLock();
-	}
-
-	/**
-		Try to acquire the mutex, returns true if acquire or false if it's already locked by another thread.
-	**/
-	public function tryAcquire():Bool
-	{
-		return this.lock.tryLock();
-	}
-
-	/**
-		The current thread acquire the mutex or wait if not available.
-		The same thread can acquire several times the same mutex, but must release it as many times it has been acquired.
-	**/
-	public function acquire():Void
-	{
-		this.lock.lock();
-	}
-
-	/**
-		Release a mutex that has been acquired by the current thread. If the current thread does not own the mutex, an exception will be thrown
-	**/
-	public function release():Void
-	{
-		this.lock.unlock();
-	}
-}
+@:deprecated typedef Mutex = sys.thread.Mutex;

+ 2 - 89
std/java/vm/Thread.hx

@@ -19,93 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
- package java.vm;
-import java.Lib;
+package java.vm;
 
 
-@:native('haxe.java.vm.Thread') class Thread
-{
-
-	@:private static var javaThreadToHaxe = new haxe.ds.WeakMap<java.lang.Thread, java.vm.Thread>();
-	@:private static var mainJavaThread = java.lang.Thread.currentThread();
-	@:private static var mainHaxeThread = {
-		var ret = new Thread();
-		javaThreadToHaxe.set(mainJavaThread, ret);
-		ret;
-	};
-
-
-	private static function getThread(jt:java.lang.Thread):Thread
-	{
-		if (Std.is(jt, HaxeThread))
-		{
-			var t:HaxeThread = cast jt;
-			return t.threadObject;
-		}
-		else if (jt == mainJavaThread)
-		{
-			return mainHaxeThread;
-		}
-		else
-		{
-			var ret = null;
-			untyped __lock__(javaThreadToHaxe, {
-				ret = javaThreadToHaxe.get(jt);
-				if (ret == null)
-				{
-					ret = new Thread();
-					javaThreadToHaxe.set(jt, ret);
-				}
-
-			});
-			return ret;
-		}
-	}
-
-	private var messages:Deque<Dynamic>;
-
-  function new()
-	{
-		this.messages = new Deque();
-	}
-
-	public function sendMessage(obj:Dynamic)
-	{
-		messages.add(obj);
-	}
-
-	public static function current():Thread
-	{
-		return getThread( java.lang.Thread.currentThread() );
-	}
-
-	public static function readMessage(block : Bool) : Dynamic
-	{
-		return current().messages.pop(block);
-	}
-
-	public static function create(fn:Void->Void):Thread
-	{
-		var ret = new Thread();
-		var t = new HaxeThread(ret, fn);
-		t.start();
-		return ret;
-	}
-}
-
-@:native('haxe.java.vm.HaxeThread')
-private class HaxeThread extends java.lang.Thread
-{
-	public var threadObject(default, null):Thread;
-	private var runFunction:Void->Void;
-	@:overload override public function run():Void
-	{
-		runFunction();
-	}
-	public function new(hxThread:Thread, run:Void->Void)
-	{
-		super();
-		threadObject = hxThread;
-		runFunction = run;
-		setDaemon(true);
-	}
-}
+@:deprecated typedef Thread = sys.thread.Thread;

+ 2 - 26
std/java/vm/Tls.hx

@@ -19,30 +19,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
- package java.vm;
+package java.vm;
 
 
-/**
-	Thread-local Storage implementation
-**/
-@:native('haxe.java.vm.Tls') class Tls<T>
-{
-	var t : java.lang.ThreadLocal<T>;
-	public var value(get,set):T;
-
-	public function new()
-	{
-		this.t = new java.lang.ThreadLocal();
-	}
-
-	inline private function get_value():T
-	{
-		return t.get();
-	}
-
-	inline private function set_value(v:T):T
-	{
-		t.set(v);
-		return v;
-	}
-
-}
+@:deprecated typedef Tls<T> = sys.thread.Tls<T>;

+ 48 - 0
std/neko/_std/sys/thread/Deque.hx

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Deque<T> {
+	var q : Dynamic;
+
+	public function new() {
+		q = deque_create();
+	}
+
+	public function add( i : T ):Void {
+		deque_add(q,i);
+	}
+
+	public function push( i : T ):Void {
+		deque_push(q,i);
+	}
+
+	public function pop( block : Bool ) : Null<T> {
+		return deque_pop(q,block);
+	}
+
+	static var deque_create = neko.Lib.loadLazy("std","deque_create",0);
+	static var deque_add = neko.Lib.loadLazy("std","deque_add",2);
+	static var deque_push = neko.Lib.loadLazy("std","deque_push",2);
+	static var deque_pop = neko.Lib.loadLazy("std","deque_pop",2);
+}

+ 43 - 0
std/neko/_std/sys/thread/Lock.hx

@@ -0,0 +1,43 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Lock {
+	var l : Dynamic;
+
+	public function new() {
+		l = lock_create();
+	}
+
+	public function wait( ?timeout : Float ) : Bool {
+		return lock_wait(l,timeout);
+	}
+
+	public function release():Void {
+		lock_release(l);
+	}
+
+	static var lock_create = neko.Lib.load("std","lock_create",0);
+	static var lock_release = neko.Lib.load("std","lock_release",1);
+	static var lock_wait = neko.Lib.load("std","lock_wait",2);
+}

+ 48 - 0
std/neko/_std/sys/thread/Mutex.hx

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Mutex {
+	var m : Dynamic;
+
+	public function new():Void {
+		m = mutex_create();
+	}
+
+	public function acquire():Void {
+		mutex_acquire(m);
+	}
+
+	public function tryAcquire() : Bool {
+		return mutex_try(m);
+	}
+
+	public function release():Void {
+		mutex_release(m);
+	}
+
+	static var mutex_create = neko.Lib.loadLazy("std","mutex_create",0);
+	static var mutex_release = neko.Lib.loadLazy("std","mutex_release",1);
+	static var mutex_acquire = neko.Lib.loadLazy("std","mutex_acquire",1);
+	static var mutex_try = neko.Lib.loadLazy("std","mutex_try",1);
+}

+ 122 - 0
std/neko/_std/sys/thread/Thread.hx

@@ -0,0 +1,122 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:callable
+@:coreType
+abstract ThreadHandle {
+}
+
+@:coreApi
+class Thread {
+
+	var handle : ThreadHandle;
+
+	function new(h:ThreadHandle):Void {
+		handle = h;
+	}
+
+	public function sendMessage( msg : Dynamic ):Void {
+		thread_send(handle,msg);
+	}
+
+	public static function current():Thread {
+		return new Thread(thread_current());
+	}
+
+	public static function create( callb : Void -> Void ):Thread {
+		return new Thread(thread_create(function(_) { return callb(); },null));
+	}
+
+	public static function readMessage( block : Bool ) : Dynamic {
+		return thread_read_message(block);
+	}
+
+	@:keep function __compare(t:Dynamic):Int {
+		return untyped __dollar__compare(handle,t.handle);
+	}
+
+	/**
+		Starts an OS message loop after [osInitialize] has been done.
+		In that state, the UI handled by this thread will be updated and
+		[sync] calls can be performed. The loop returns when [exitLoop] is
+		called for this thread.
+	**
+	public static function osLoop() {
+		if( os_loop == null ) throw "Please call osInitialize() first";
+		os_loop();
+	}
+
+	/**
+		The function [f] will be called by this thread if it's in [osLoop].
+		[sync] returns immediately. See [osInitialize] remarks.
+	**
+	public function sync( f : Void -> Void ) {
+		os_sync(handle,f);
+	}
+
+	/**
+		The function [f] will be called by this thread and the calling thread
+		will wait until the result is available then return its value.
+	**
+	public function syncResult<T>( f : Void -> T ) : T {
+		if( this == current() )
+			return f();
+		var v = new neko.vm.Lock();
+		var r = null;
+		sync(function() {
+			r = f();
+			v.release();
+		});
+		v.wait();
+		return r;
+	}
+
+	/**
+		Exit from [osLoop].
+	**
+	public function exitLoop() {
+		os_loop_stop(handle);
+	}
+
+	/**
+		If you want to use the [osLoop], [sync] and [syncResult] methods, you
+		need to call [osInitialize] before creating any thread or calling [current].
+		This will load [os.ndll] library and initialize UI methods for each thread.
+	**
+	public static function osInitialize() {
+		os_loop = neko.Lib.load("os","os_loop",0);
+		os_loop_stop = neko.Lib.load("os","os_loop_stop",1);
+		os_sync = neko.Lib.load("os","os_sync",2);
+	}
+
+	static var os_loop = null;
+	static var os_loop_stop = null;
+	static var os_sync = null;
+	*/
+
+	static var thread_create = neko.Lib.load("std","thread_create",2);
+	static var thread_current = neko.Lib.load("std","thread_current",0);
+	static var thread_send = neko.Lib.load("std","thread_send",2);
+	static var thread_read_message = neko.Lib.load("std","thread_read_message",1);
+
+}

+ 46 - 0
std/neko/_std/sys/thread/Tls.hx

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package sys.thread;
+
+@:coreApi
+class Tls<T> {
+
+	var t : Dynamic;
+	public var value(get,set) : T;
+
+	public function new() {
+		t = tls_create();
+	}
+
+	function get_value() : T {
+		return tls_get(t);
+	}
+
+	function set_value( v : T ):T {
+		tls_set(t,v);
+		return v;
+	}
+
+	static var tls_create = neko.Lib.load("std","tls_create",0);
+	static var tls_get = neko.Lib.load("std","tls_get",1);
+	static var tls_set = neko.Lib.load("std","tls_set",2);
+}

+ 1 - 40
std/neko/vm/Deque.hx

@@ -21,43 +21,4 @@
  */
  */
 package neko.vm;
 package neko.vm;
 
 
-/**
-	A message queue for multithread access.
-*/
-class Deque<T> {
-	var q : Dynamic;
-
-	/**
-		Create a message queue for multithread access.
-	**/
-	public function new() {
-		q = deque_create();
-	}
-
-	/**
-		Add a message at the end of the queue.
-	**/
-	public function add( i : T ) {
-		deque_add(q,i);
-	}
-
-	/**
-		Add a message at the head of the queue.
-	**/
-	public function push( i : T ) {
-		deque_push(q,i);
-	}
-
-	/**
-		Pop a message from the queue head. Either block until a message 
-		is available or return immediately with `null`.
-	**/
-	public function pop( block : Bool ) : Null<T> {
-		return deque_pop(q,block);
-	}
-
-	static var deque_create = neko.Lib.loadLazy("std","deque_create",0);
-	static var deque_add = neko.Lib.loadLazy("std","deque_add",2);
-	static var deque_push = neko.Lib.loadLazy("std","deque_push",2);
-	static var deque_pop = neko.Lib.loadLazy("std","deque_pop",2);
-}
+@:deprecated typedef Deque<T> = sys.thread.Deque<T>;

+ 1 - 32
std/neko/vm/Lock.hx

@@ -21,35 +21,4 @@
  */
  */
 package neko.vm;
 package neko.vm;
 
 
-class Lock {
-	var l : Dynamic;
-
-	/**
-		Creates a lock which is initially locked.
-	**/
-	public function new() {
-		l = lock_create();
-	}
-
-	/**
-		Waits for a lock to be released and acquire it. If timeout 
-		(in seconds) is not `null` and expires then the returned 
-		value is `false`.
-	**/
-	public function wait( ?timeout : Float ) : Bool {
-		return lock_wait(l,timeout);
-	}
-	
-	/**
-		Release a lock. The thread does not need to own the lock 
-		to be able to release it. If a lock is released several 
-		times, it can be acquired as many times.
-	**/
-	public function release() {
-		lock_release(l);
-	}
-
-	static var lock_create = neko.Lib.load("std","lock_create",0);
-	static var lock_release = neko.Lib.load("std","lock_release",1);
-	static var lock_wait = neko.Lib.load("std","lock_wait",2);
-}
+@:deprecated typedef Lock = sys.thread.Lock;

+ 1 - 46
std/neko/vm/Mutex.hx

@@ -21,49 +21,4 @@
  */
  */
 package neko.vm;
 package neko.vm;
 
 
-/**
-	Creates a mutex, which can be used to acquire a temporary lock 
-	to access some ressource. The main difference with a lock is 
-	that a mutex must always be released by the owner thread.
-*/
-class Mutex {
-	var m : Dynamic;
-
-	/**
-		Creates a mutex.
-	**/
-	public function new() {
-		m = mutex_create();
-	}
-
-	/**
-		The current thread acquire the mutex or wait if not available.
-		The same thread can acquire several times the same mutex but 
-		must release it as many times it has been acquired.
-	**/
-	public function acquire() {
-		mutex_acquire(m);
-	}
-
-	/**
-		Try to acquire the mutex, returns true if acquire or false 
-		if it's already locked by another thread.
-	**/
-	public function tryAcquire() : Bool {
-		return mutex_try(m);
-	}
-
-	/**
-		Release a mutex that has been acquired by the current thread. 
-		The behavior is undefined if the current thread does not own
-		the mutex.
-	**/
-	public function release() {
-		mutex_release(m);
-	}
-
-	static var mutex_create = neko.Lib.loadLazy("std","mutex_create",0);
-	static var mutex_release = neko.Lib.loadLazy("std","mutex_release",1);
-	static var mutex_acquire = neko.Lib.loadLazy("std","mutex_acquire",1);
-	static var mutex_try = neko.Lib.loadLazy("std","mutex_try",1);
-}
+@:deprecated typedef Mutex = sys.thread.Mutex;

+ 1 - 113
std/neko/vm/Thread.hx

@@ -21,116 +21,4 @@
  */
  */
 package neko.vm;
 package neko.vm;
 
 
-@:callable
-@:coreType
-abstract ThreadHandle {
-}
-
-class Thread {
-
-	var handle : ThreadHandle;
-
-	function new(h) {
-		handle = h;
-	}
-
-	/**
-		Send a message to the thread queue. This message can be read by using `readMessage`.
-	**/
-	public function sendMessage( msg : Dynamic ) {
-		thread_send(handle,msg);
-	}
-
-
-	/**
-		Returns the current thread.
-	**/
-	public static function current() {
-		return new Thread(thread_current());
-	}
-
-	/**
-		Creates a new thread that will execute the `callb` function, then exit.
-	**/
-	public static function create( callb : Void -> Void ) {
-		return new Thread(thread_create(function(_) { return callb(); },null));
-	}
-
-	/**
-		Reads a message from the thread queue. If `block` is true, the function
-		blocks until a message is available. If `block` is false, the function
-		returns `null` if no message is available.
-	**/
-	public static function readMessage( block : Bool ) : Dynamic {
-		return thread_read_message(block);
-	}
-
-	@:keep function __compare(t:Dynamic) {
-		return untyped __dollar__compare(handle,t.handle);
-	}
-
-	/**
-		Starts an OS message loop after [osInitialize] has been done.
-		In that state, the UI handled by this thread will be updated and
-		[sync] calls can be performed. The loop returns when [exitLoop] is
-		called for this thread.
-	**
-	public static function osLoop() {
-		if( os_loop == null ) throw "Please call osInitialize() first";
-		os_loop();
-	}
-
-	/**
-		The function [f] will be called by this thread if it's in [osLoop].
-		[sync] returns immediately. See [osInitialize] remarks.
-	**
-	public function sync( f : Void -> Void ) {
-		os_sync(handle,f);
-	}
-
-	/**
-		The function [f] will be called by this thread and the calling thread
-		will wait until the result is available then return its value.
-	**
-	public function syncResult<T>( f : Void -> T ) : T {
-		if( this == current() )
-			return f();
-		var v = new neko.vm.Lock();
-		var r = null;
-		sync(function() {
-			r = f();
-			v.release();
-		});
-		v.wait();
-		return r;
-	}
-
-	/**
-		Exit from [osLoop].
-	**
-	public function exitLoop() {
-		os_loop_stop(handle);
-	}
-
-	/**
-		If you want to use the [osLoop], [sync] and [syncResult] methods, you
-		need to call [osInitialize] before creating any thread or calling [current].
-		This will load [os.ndll] library and initialize UI methods for each thread.
-	**
-	public static function osInitialize() {
-		os_loop = neko.Lib.load("os","os_loop",0);
-		os_loop_stop = neko.Lib.load("os","os_loop_stop",1);
-		os_sync = neko.Lib.load("os","os_sync",2);
-	}
-
-	static var os_loop = null;
-	static var os_loop_stop = null;
-	static var os_sync = null;
-	*/
-
-	static var thread_create = neko.Lib.load("std","thread_create",2);
-	static var thread_current = neko.Lib.load("std","thread_current",0);
-	static var thread_send = neko.Lib.load("std","thread_send",2);
-	static var thread_read_message = neko.Lib.load("std","thread_read_message",1);
-
-}
+@:deprecated typedef Thread = sys.thread.Thread;

+ 1 - 37
std/neko/vm/Tls.hx

@@ -21,40 +21,4 @@
  */
  */
 package neko.vm;
 package neko.vm;
 
 
-/**
-	Creates thread local storage.
-*/
-class Tls<T> {
-
-	var t : Dynamic;
-	public var value(get,set) : T;
-
-	/**
-		Creates thread local storage. This is placeholder that can store
-		a value that will be different depending on the local thread. 
-		Set the tls value to `null` before exiting the thread 
-		or the memory will never be collected.
-	**/
-	public function new() {
-		t = tls_create();
-	}
-
-	/**
-		Returns the value set by tls_set for the local thread.
-	**/
-	function get_value() : T {
-		return tls_get(t);
-	}
-
-	/**
-		Set the value of the TLS for the local thread.
-	**/
-	function set_value( v : T ) {
-		tls_set(t,v);
-		return v;
-	}
-
-	static var tls_create = neko.Lib.load("std","tls_create",0);
-	static var tls_get = neko.Lib.load("std","tls_get",1);
-	static var tls_set = neko.Lib.load("std","tls_set",2);
-}
+@:deprecated typedef Tls<T> = sys.thread.Tls<T>;

+ 59 - 0
std/sys/thread/Deque.hx

@@ -0,0 +1,59 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package sys.thread;
+
+#if (!target.threaded)
+#error "This class is not available on this target"
+#end
+
+/**
+	A Deque is a double-ended queue with a `pop` method that can block until
+	an element is available. It is commonly used to synchronize threads.
+ */
+@:coreApi extern class Deque<T> {
+	/**
+		Create a new Deque instance which is initially empty.
+	**/
+	public function new():Void;
+
+	/**
+		Adds an element at the end of `this` Deque.
+	**/
+	public function add(i:T):Void;
+
+	/**
+		Adds an element at the front of `this` Deque.
+	**/
+	public function push(i:T):Void;
+
+	/**
+		Tries to retrieve an element from the front of `this` Deque.
+
+		If an element is available, it is removed from the queue and returned.
+
+		If no element is available and `block` is `false`, `null` is returned.
+
+		Otherwise, execution blocks until an element is available and returns it.
+	**/
+	public function pop(block:Bool):Null<T>;
+}

+ 80 - 0
std/sys/thread/Lock.hx

@@ -0,0 +1,80 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package sys.thread;
+
+#if (!target.threaded)
+#error "This class is not available on this target"
+#end
+
+/**
+	A Lock allows blocking execution until it has been unlocked. It keeps track
+	of how often `release` has been called, and blocks exactly as many `wait`
+	calls.
+
+	The order of the `release` and `wait` calls is irrelevant. That is, a Lock
+	can be released before anyone waits for it. In that case, the `wait` call
+	will execute immediately.
+
+	Usage example:
+
+	```
+		var lock = new Lock();
+		var elements = [1, 2, 3];
+		for (element in elements) {
+			// Create one thread per element
+			new Thread(function() {
+				trace(element);
+				Sys.sleep(1);
+				// Release once per thread = 3 times
+				lock.release();
+			});
+		}
+		for (_ in elements) {
+			// Wait 3 times
+			lock.wait();
+		}
+		trace("All threads finished");
+	```
+**/
+extern class Lock {
+	/**
+		Creates a new Lock which is initially locked.
+	**/
+	public function new():Void;
+
+	/**
+		Waits for the lock to be released, or `timeout` (in seconds)
+		to expire. Returns `true` if the lock is released and `false`
+		if a time-out occurs.
+	**/
+	public function wait(?timeout:Float):Bool;
+
+	/**
+		Releases the lock once.
+
+		The thread does not need to own the lock in order to release
+		it. Each call to `release` allows exactly one call to `wait`
+		to execute.
+	**/
+	public function release():Void;
+}

+ 59 - 0
std/sys/thread/Mutex.hx

@@ -0,0 +1,59 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package sys.thread;
+
+#if (!target.threaded)
+#error "This class is not available on this target"
+#end
+
+/**
+	Creates a mutex, which can be used to acquire a temporary lock
+	to access some ressource. The main difference with a lock is
+	that a mutex must always be released by the owner thread.
+ */
+extern class Mutex {
+	/**
+		Creates a mutex.
+	**/
+	public function new():Void;
+
+	/**
+		The current thread acquire the mutex or wait if not available.
+		The same thread can acquire several times the same mutex but
+		must release it as many times it has been acquired.
+	**/
+	public function acquire():Void;
+
+	/**
+		Try to acquire the mutex, returns true if acquire or false
+		if it's already locked by another thread.
+	**/
+	public function tryAcquire():Bool;
+
+	/**
+		Release a mutex that has been acquired by the current thread.
+		The behavior is undefined if the current thread does not own
+		the mutex.
+	**/
+	public function release():Void;
+}

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

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package sys.thread;
+
+#if (!target.threaded)
+#error "This class is not available on this target"
+#end
+extern class Thread {
+	/**
+		Send a message to the thread queue. This message can be read by using `readMessage`.
+	**/
+	public function sendMessage(msg:Dynamic):Void;
+
+	/**
+		Returns the current thread.
+	**/
+	public static function current():Thread;
+
+	/**
+		Creates a new thread that will execute the `f` function, then exit.
+	**/
+	public static function create(callb:Void->Void):Thread;
+
+	/**
+		Reads a message from the thread queue. If `block` is true, the function
+		blocks until a message is available. If `block` is false, the function
+		returns `null` if no message is available.
+	**/
+	public static function readMessage(block:Bool):Dynamic;
+}

+ 42 - 0
std/sys/thread/Tls.hx

@@ -0,0 +1,42 @@
+/*
+ * Copyright (C)2005-2019 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package sys.thread;
+
+#if (!target.threaded)
+#error "This class is not available on this target"
+#end
+
+/**
+	Creates thread local storage.
+ */
+extern class Tls<T> {
+	public var value(get, set):T;
+
+	/**
+		Creates thread local storage. This is placeholder that can store
+		a value that will be different depending on the local thread.
+		Set the tls value to `null` before exiting the thread
+		or the memory will never be collected.
+	**/
+	public function new():Void;
+}

+ 5 - 31
tests/threads/src/import.hx

@@ -1,31 +1,5 @@
-#if neko
-import neko.vm.Thread;
-import neko.vm.Deque;
-import neko.vm.Lock;
-import neko.vm.Tls;
-import neko.vm.Mutex;
-#elseif cpp
-import cpp.vm.Thread;
-import cpp.vm.Deque;
-import cpp.vm.Lock;
-import cpp.vm.Tls;
-import cpp.vm.Mutex;
-#elseif java
-import java.vm.Thread;
-import java.vm.Deque;
-import java.vm.Lock;
-import java.vm.Tls;
-import java.vm.Mutex;
-#elseif eval
-import eval.vm.Thread;
-import eval.vm.Deque;
-import eval.vm.Lock;
-import eval.vm.Tls;
-import eval.vm.Mutex;
-#elseif hl
-import hl.vm.Thread;
-import hl.vm.Deque;
-// import hl.vm.Lock; // TODO
-import hl.vm.Tls;
-import hl.vm.Mutex;
-#end
+import sys.thread.Thread;
+import sys.thread.Deque;
+import sys.thread.Lock;
+import sys.thread.Tls;
+import sys.thread.Mutex;

+ 5 - 25
tests/unit/src/unit/TestThreads.hx

@@ -1,30 +1,10 @@
 package unit;
 package unit;
 import utest.Assert;
 import utest.Assert;
-#if neko
-import neko.vm.Thread;
-import neko.vm.Deque;
-import neko.vm.Lock;
-import neko.vm.Tls;
-import neko.vm.Mutex;
-#elseif cpp
-import cpp.vm.Thread;
-import cpp.vm.Deque;
-import cpp.vm.Lock;
-import cpp.vm.Tls;
-import cpp.vm.Mutex;
-#elseif java
-import java.vm.Thread;
-import java.vm.Deque;
-import java.vm.Lock;
-import java.vm.Tls;
-import java.vm.Mutex;
-#elseif eval
-import eval.vm.Thread;
-import eval.vm.Deque;
-import eval.vm.Lock;
-import eval.vm.Tls;
-import eval.vm.Mutex;
-#end
+import sys.thread.Thread;
+import sys.thread.Deque;
+import sys.thread.Lock;
+import sys.thread.Tls;
+import sys.thread.Mutex;
 
 
 class TestThreads extends Test
 class TestThreads extends Test
 {
 {

+ 3 - 3
tests/unit/src/unit/issues/Issue3084.hx

@@ -8,13 +8,13 @@ class Issue3084 extends Test
 	{
 	{
 		for (i in 0...40)
 		for (i in 0...40)
 		{
 		{
-			var m = new java.vm.Mutex();
-			java.vm.Thread.create(function():Void {
+			var m = new sys.thread.Mutex();
+			sys.thread.Thread.create(function():Void {
 				m.acquire();
 				m.acquire();
 				Sys.sleep(0.01);
 				Sys.sleep(0.01);
 				m.release();
 				m.release();
 			});
 			});
-			java.vm.Thread.create(function():Void {
+			sys.thread.Thread.create(function():Void {
 				m.acquire();
 				m.acquire();
 				Sys.sleep(0.01);
 				Sys.sleep(0.01);
 				m.release();
 				m.release();

+ 2 - 6
tests/unit/src/unit/issues/Issue3767.hx

@@ -1,11 +1,7 @@
 package unit.issues;
 package unit.issues;
 import unit.Test;
 import unit.Test;
-#if java
-import java.vm.*;
-#elseif neko
-import neko.vm.*;
-#elseif cpp
-import cpp.vm.*;
+#if (java || neko || cpp)
+import sys.thread.*;
 #end
 #end
 
 
 class Issue3767 extends Test
 class Issue3767 extends Test

+ 2 - 2
tests/unit/src/unit/issues/Issue4878.hx

@@ -1,7 +1,7 @@
 package unit.issues;
 package unit.issues;
 #if java
 #if java
-import java.vm.Thread;
-import java.vm.Mutex;
+import sys.thread.Thread;
+import sys.thread.Mutex;
 #end
 #end
 
 
 class Issue4878 extends Test {
 class Issue4878 extends Test {