Update Files
This commit is contained in:
		
							
								
								
									
										140
									
								
								Kha/Tools/macos/std/eval/_std/sys/thread/EventLoop.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Kha/Tools/macos/std/eval/_std/sys/thread/EventLoop.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,140 @@
 | 
			
		||||
package sys.thread;
 | 
			
		||||
 | 
			
		||||
import eval.luv.Loop;
 | 
			
		||||
import eval.luv.Async;
 | 
			
		||||
import eval.luv.Timer as LuvTimer;
 | 
			
		||||
 | 
			
		||||
@:coreApi
 | 
			
		||||
enum NextEventTime {
 | 
			
		||||
	Now;
 | 
			
		||||
	Never;
 | 
			
		||||
	AnyTime(time:Null<Float>);
 | 
			
		||||
	At(time:Float);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract EventHandler(RegularEvent) from RegularEvent to RegularEvent {}
 | 
			
		||||
 | 
			
		||||
private class RegularEvent {
 | 
			
		||||
	public var timer:Null<LuvTimer>;
 | 
			
		||||
	public var event:()->Void;
 | 
			
		||||
 | 
			
		||||
	public function new(e:()->Void) {
 | 
			
		||||
		event = e;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function run() {
 | 
			
		||||
		event();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@:coreApi
 | 
			
		||||
class EventLoop {
 | 
			
		||||
	@:allow(eval.luv.Loop)
 | 
			
		||||
	final handle:Loop;
 | 
			
		||||
 | 
			
		||||
	final mutex = new Mutex();
 | 
			
		||||
	final oneTimeEvents = new Array<Null<()->Void>>();
 | 
			
		||||
	var oneTimeEventsIdx = 0;
 | 
			
		||||
	final wakeup:Async;
 | 
			
		||||
	var promisedEventsCount = 0;
 | 
			
		||||
	var pending:Array<()->Void> = [];
 | 
			
		||||
	var looping = false;
 | 
			
		||||
 | 
			
		||||
	public function new():Void {
 | 
			
		||||
		handle = Loop.init().resolve();
 | 
			
		||||
		wakeup = Async.init(handle, consumePending).resolve();
 | 
			
		||||
		wakeup.unref();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function repeat(event:()->Void, intervalMs:Int):EventHandler {
 | 
			
		||||
		var e = new RegularEvent(event);
 | 
			
		||||
		mutex.acquire();
 | 
			
		||||
		pending.push(() -> {
 | 
			
		||||
			e.timer = LuvTimer.init(handle).resolve();
 | 
			
		||||
			e.timer.start(e.run, intervalMs, intervalMs < 1 ? 1 : intervalMs).resolve();
 | 
			
		||||
		});
 | 
			
		||||
		mutex.release();
 | 
			
		||||
		wakeup.send();
 | 
			
		||||
		return e;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function cancel(eventHandler:EventHandler):Void {
 | 
			
		||||
		mutex.acquire();
 | 
			
		||||
		(eventHandler:RegularEvent).event = noop;
 | 
			
		||||
		pending.push(() -> {
 | 
			
		||||
			var timer = (eventHandler:RegularEvent).timer;
 | 
			
		||||
			timer.stop().resolve();
 | 
			
		||||
			timer.close(noop);
 | 
			
		||||
		});
 | 
			
		||||
		mutex.release();
 | 
			
		||||
		wakeup.send();
 | 
			
		||||
	}
 | 
			
		||||
	static final noop = function() {}
 | 
			
		||||
 | 
			
		||||
	public function promise():Void {
 | 
			
		||||
		mutex.acquire();
 | 
			
		||||
		++promisedEventsCount;
 | 
			
		||||
		pending.push(refUnref);
 | 
			
		||||
		mutex.release();
 | 
			
		||||
		wakeup.send();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function run(event:()->Void):Void {
 | 
			
		||||
		mutex.acquire();
 | 
			
		||||
		pending.push(event);
 | 
			
		||||
		mutex.release();
 | 
			
		||||
		wakeup.send();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function runPromised(event:()->Void):Void {
 | 
			
		||||
		mutex.acquire();
 | 
			
		||||
		--promisedEventsCount;
 | 
			
		||||
		pending.push(refUnref);
 | 
			
		||||
		pending.push(event);
 | 
			
		||||
		mutex.release();
 | 
			
		||||
		wakeup.send();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function refUnref():Void {
 | 
			
		||||
		if(promisedEventsCount > 0) {
 | 
			
		||||
			wakeup.ref();
 | 
			
		||||
		} else {
 | 
			
		||||
			wakeup.unref();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function progress():NextEventTime {
 | 
			
		||||
		//TODO: throw if loop is already running
 | 
			
		||||
		if((handle:Loop).run(NOWAIT)) {
 | 
			
		||||
			return AnyTime(null);
 | 
			
		||||
		} else {
 | 
			
		||||
			return Never;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function wait(?timeout:Float):Bool {
 | 
			
		||||
		//TODO: throw if loop is already running
 | 
			
		||||
		if(timeout == null) {
 | 
			
		||||
			var timer = LuvTimer.init(handle).resolve();
 | 
			
		||||
			timer.start(() -> {
 | 
			
		||||
				timer.stop().resolve();
 | 
			
		||||
				timer.close(() -> {});
 | 
			
		||||
			}, Std.int(timeout * 1000));
 | 
			
		||||
			return (handle:Loop).run(ONCE);
 | 
			
		||||
		} else {
 | 
			
		||||
			return (handle:Loop).run(ONCE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function loop():Void {
 | 
			
		||||
		//TODO: throw if loop is already running
 | 
			
		||||
		consumePending();
 | 
			
		||||
		(handle:Loop).run(DEFAULT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function consumePending(?_:Async):Void {
 | 
			
		||||
		var p = pending;
 | 
			
		||||
		pending = [];
 | 
			
		||||
		for(fn in p) fn();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										105
									
								
								Kha/Tools/macos/std/eval/_std/sys/thread/Thread.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								Kha/Tools/macos/std/eval/_std/sys/thread/Thread.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 eval.vm.NativeThread;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public inline function sendMessage(msg:Dynamic):Void {
 | 
			
		||||
		this.sendMessage(msg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function current():Thread {
 | 
			
		||||
		return new Thread(NativeThread.self());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function create(job:()->Void):Thread {
 | 
			
		||||
		return new Thread(new NativeThread(job));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static function runWithEventLoop(job:()->Void):Void {
 | 
			
		||||
		var thread = NativeThread.self();
 | 
			
		||||
		if(thread.events == null) {
 | 
			
		||||
			thread.events = new EventLoop();
 | 
			
		||||
			try {
 | 
			
		||||
				job();
 | 
			
		||||
				thread.events.loop();
 | 
			
		||||
				thread.events = null;
 | 
			
		||||
			} catch(e) {
 | 
			
		||||
				thread.events = null;
 | 
			
		||||
				throw e;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			job();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function createWithEventLoop(job:()->Void):Thread {
 | 
			
		||||
		return new Thread(new NativeThread(() -> {
 | 
			
		||||
			var thread = NativeThread.self();
 | 
			
		||||
			thread.events = new EventLoop();
 | 
			
		||||
			job();
 | 
			
		||||
			thread.events.loop();
 | 
			
		||||
		}));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function readMessage(block:Bool):Dynamic {
 | 
			
		||||
		return NativeThread.readMessage(block);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function yield():Void {
 | 
			
		||||
		NativeThread.yield();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@:op(A == B)
 | 
			
		||||
	public inline function equals(other:Thread):Bool {
 | 
			
		||||
		return getHandle().id() == other.getHandle().id();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline function getHandle():NativeThread {
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function get_events():EventLoop {
 | 
			
		||||
		if(this.events == null)
 | 
			
		||||
			throw new NoEventLoopException();
 | 
			
		||||
		return this.events;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@:keep
 | 
			
		||||
	static function processEvents():Void {
 | 
			
		||||
		NativeThread.self().events.loop();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user