Parcourir la source

[eval] bring back eval.vm.Thread

But please don't use it...

closes #6797
Simon Krajewski il y a 7 ans
Parent
commit
3d7650fa8b

+ 5 - 2
src/macro/eval/evalContext.ml

@@ -194,6 +194,7 @@ and context = {
 	(* eval *)
 	toplevel : value;
 	eval : eval;
+	evals : eval DynArray.t;
 	mutable exception_stack : (pos * env_kind) list;
 }
 
@@ -204,7 +205,8 @@ let select ctx = get_ctx_ref := (fun() -> ctx)
 (* Misc *)
 
 let get_eval ctx =
-	ctx.eval
+    let id = Thread.id (Thread.self()) in
+    if id = 0 then ctx.eval else DynArray.unsafe_get ctx.evals id
 
 let rec kind_name ctx kind =
 	let rec loop kind env_id = match kind, env_id with
@@ -241,7 +243,8 @@ let proto_fields proto =
 exception RunTimeException of value * env list * pos
 
 let call_stack ctx =
-	List.rev (DynArray.to_list (DynArray.sub ctx.eval.environments 0 ctx.eval.environment_offset))
+	let eval = get_eval ctx in
+	List.rev (DynArray.to_list (DynArray.sub eval.environments 0 eval.environment_offset))
 
 let throw v p =
 	let ctx = get_ctx() in

+ 1 - 0
src/macro/eval/evalMain.ml

@@ -131,6 +131,7 @@ let create com api is_macro =
 			oproto = fake_proto key_eval_toplevel;
 		};
 		eval = eval;
+		evals = evals;
 		exception_stack = [];
 	} in
 	t();

+ 70 - 0
src/macro/eval/evalStdLib.ml

@@ -2478,6 +2478,45 @@ module StdSys = struct
 	let time = vfun0 (fun () -> vfloat (Unix.gettimeofday()))
 end
 
+module StdThread = struct
+	let this vthis = match vthis with
+		| VInstance {ikind = IThread thread} -> thread
+		| _ -> unexpected_value vthis "Thread"
+
+	let delay = vfun1 (fun f ->
+		Thread.delay (num f);
+		vnull
+	)
+
+	let exit = vfun0 (fun () ->
+		Thread.exit();
+		vnull
+	)
+
+	let id = vifun0 (fun vthis ->
+		vint (Thread.id (this vthis))
+	)
+
+	let join = vfun1 (fun thread ->
+		Thread.join (this thread);
+		vnull
+	)
+
+	let kill = vifun0 (fun vthis ->
+		Thread.kill (this vthis);
+		vnull
+	)
+
+	let self = vfun0 (fun () ->
+		encode_instance key_eval_vm_Thread ~kind:(IThread (Thread.self()))
+	)
+
+	let yield = vfun0 (fun () ->
+		Thread.yield();
+		vnull
+	)
+end
+
 module StdType = struct
 	open Ast
 
@@ -2925,6 +2964,27 @@ let init_constructors builtins =
 				let z = Extc.zlib_inflate_init2 windowBits in
 				encode_instance key_haxe_zip_Uncompress ~kind:(IZip { z = z; z_flush = Extc.Z_NO_FLUSH })
 			| _ -> assert false
+		);
+	add key_eval_vm_Thread
+		(fun vl -> match vl with
+			| [f] ->
+				let ctx = get_ctx() in
+				if ctx.is_macro then exc_string "Creating threads in macros is not supported";
+				let f () =
+					let id = Thread.id (Thread.self()) in
+					let new_eval = {environments = DynArray.create (); environment_offset = 0} in
+					if DynArray.length ctx.evals = id then
+						DynArray.add ctx.evals new_eval
+					else
+						DynArray.set ctx.evals id new_eval;
+					try
+						ignore(call_value f []);
+					with RunTimeException(v,stack,p) ->
+						let msg = get_exc_error_message ctx v stack p in
+						prerr_endline msg
+				in
+				encode_instance key_eval_vm_Thread ~kind:(IThread (Thread.create f ()))
+			| _ -> assert false
 		)
 
 let init_empty_constructors builtins =
@@ -3278,6 +3338,16 @@ let init_standard_library builtins =
 		"systemName",StdSys.systemName;
 		"time",StdSys.time;
 	] [];
+	init_fields builtins (["eval";"vm"],"Thread") [
+		"delay",StdThread.delay;
+		"exit",StdThread.exit;
+		"join",StdThread.join;
+		"self",StdThread.self;
+		"yield",StdThread.yield;
+	] [
+		"id",StdThread.id;
+		"kill",StdThread.kill;
+	];
 	init_fields builtins ([],"Type") [
 		"allEnums",StdType.allEnums;
 		"createEmptyInstance",StdType.createEmptyInstance;

+ 79 - 0
std/eval/vm/Thread.hx

@@ -0,0 +1,79 @@
+/*
+ * Copyright (C)2005-2018 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 eval.vm;
+
+/**
+	Experimental Thread API.
+
+	Note that the debugger does not properly support threads at the moment.
+**/
+extern class Thread {
+	/**
+		Creates a new thread that executes function `f`.
+
+		Exceptions caused while executing `f` are printed to stderr and are not
+		propagated to the parent thread.
+	**/
+	function new(f:Void -> Void):Void;
+
+	/**
+		Return the identifier of the given thread. A thread identifier is an integer
+		that identifies uniquely the thread. It can be used to build data structures
+		indexed by threads.
+	**/
+	function id():Int;
+
+	/**
+		Terminate prematurely the thread whose handle is given. This functionality is
+		available only with bytecode-level threads.
+	**/
+	function kill():Int;
+
+	/**
+		Suspends the execution of the calling thread for `f` seconds. The other program
+		threads continue to run during this time.
+	**/
+	static function delay(f:Float):Void;
+
+	/**
+		Terminate prematurely the currently executing thread.
+	**/
+	static function exit():Void;
+
+	/**
+		Suspends the execution of the calling thread until the thread `thread` has
+		terminated.
+	**/
+	static function join(thread:Thread):Void;
+
+	/**
+		Return the thread currently executing.
+	**/
+	static function self():Thread;
+
+	/**
+		Re-schedule the calling thread without suspending it. This function can be used
+		to give scheduling hints, telling the scheduler that now is a good time to switch
+		to other threads.
+	**/
+	static function yield():Void;
+}