forked from LeenkxTeam/LNXSDK
		
	Update Files
This commit is contained in:
		
							
								
								
									
										211
									
								
								Kha/Tools/macos/std/haxe/MainLoop.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								Kha/Tools/macos/std/haxe/MainLoop.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,211 @@ | ||||
| package haxe; | ||||
|  | ||||
| import haxe.EntryPoint; | ||||
| #if (target.threaded && !cppia) | ||||
| import sys.thread.EventLoop; | ||||
| import sys.thread.Thread; | ||||
| #end | ||||
|  | ||||
| class MainEvent { | ||||
| 	var f:Void->Void; | ||||
| 	var prev:MainEvent; | ||||
| 	var next:MainEvent; | ||||
|  | ||||
| 	/** | ||||
| 		Tells if the event can lock the process from exiting (default:true) | ||||
| 	**/ | ||||
| 	public var isBlocking:Bool = true; | ||||
|  | ||||
| 	public var nextRun(default, null):Float; | ||||
| 	public var priority(default, null):Int; | ||||
|  | ||||
| 	function new(f, p) { | ||||
| 		this.f = f; | ||||
| 		this.priority = p; | ||||
| 		nextRun = Math.NEGATIVE_INFINITY; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 		Delay the execution of the event for the given time, in seconds. | ||||
| 		If t is null, the event will be run at tick() time. | ||||
| 	**/ | ||||
| 	public function delay(t:Null<Float>) { | ||||
| 		nextRun = t == null ? Math.NEGATIVE_INFINITY : haxe.Timer.stamp() + t; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 		Call the event. Will do nothing if the event has been stopped. | ||||
| 	**/ | ||||
| 	public inline function call() { | ||||
| 		if (f != null) | ||||
| 			f(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 		Stop the event from firing anymore. | ||||
| 	**/ | ||||
| 	public function stop() { | ||||
| 		if (f == null) | ||||
| 			return; | ||||
| 		f = null; | ||||
| 		nextRun = Math.NEGATIVE_INFINITY; | ||||
| 		if (prev == null) | ||||
| 			@:privateAccess MainLoop.pending = next; | ||||
| 		else | ||||
| 			prev.next = next; | ||||
| 		if (next != null) | ||||
| 			next.prev = prev; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @:access(haxe.MainEvent) | ||||
| class MainLoop { | ||||
| 	#if (target.threaded && !cppia) | ||||
| 	static var eventLoopHandler:Null<EventHandler>; | ||||
| 	static var mutex = new sys.thread.Mutex(); | ||||
| 	static var mainThread = Thread.current(); | ||||
| 	#end | ||||
|  | ||||
| 	static var pending:MainEvent; | ||||
|  | ||||
| 	public static var threadCount(get, never):Int; | ||||
|  | ||||
| 	inline static function get_threadCount() | ||||
| 		return EntryPoint.threadCount; | ||||
|  | ||||
| 	public static function hasEvents() { | ||||
| 		var p = pending; | ||||
| 		while (p != null) { | ||||
| 			if (p.isBlocking) | ||||
| 				return true; | ||||
| 			p = p.next; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	public static function addThread(f:Void->Void) { | ||||
| 		EntryPoint.addThread(f); | ||||
| 	} | ||||
|  | ||||
| 	public static function runInMainThread(f:Void->Void) { | ||||
| 		EntryPoint.runInMainThread(f); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 		Add a pending event to be run into the main loop. | ||||
| 	**/ | ||||
| 	public static function add(f:Void->Void, priority = 0):MainEvent@:privateAccess { | ||||
| 		if (f == null) | ||||
| 			throw "Event function is null"; | ||||
| 		var e = new MainEvent(f, priority); | ||||
| 		var head = pending; | ||||
| 		if (head != null) | ||||
| 			head.prev = e; | ||||
| 		e.next = head; | ||||
| 		pending = e; | ||||
| 		injectIntoEventLoop(0); | ||||
| 		return e; | ||||
| 	} | ||||
|  | ||||
| 	static function injectIntoEventLoop(waitMs:Int) { | ||||
| 		#if (target.threaded && !cppia) | ||||
| 			mutex.acquire(); | ||||
| 			if(eventLoopHandler != null) | ||||
| 				mainThread.events.cancel(eventLoopHandler); | ||||
| 			eventLoopHandler = mainThread.events.repeat( | ||||
| 				() -> { | ||||
| 					mainThread.events.cancel(eventLoopHandler); | ||||
| 					var wait = tick(); | ||||
| 					if(hasEvents()) { | ||||
| 						injectIntoEventLoop(Std.int(wait * 1000)); | ||||
| 					} | ||||
| 				}, | ||||
| 				waitMs | ||||
| 			); | ||||
| 			mutex.release(); | ||||
| 		#end | ||||
| 	} | ||||
|  | ||||
| 	static function sortEvents() { | ||||
| 		// pending = haxe.ds.ListSort.sort(pending, function(e1, e2) return e1.nextRun > e2.nextRun ? -1 : 1); | ||||
| 		// we can't use directly ListSort because it requires prev/next to be public, which we don't want here | ||||
| 		// we do then a manual inline, this also allow use to do a Float comparison of nextRun | ||||
| 		var list = pending; | ||||
|  | ||||
| 		if (list == null) | ||||
| 			return; | ||||
|  | ||||
| 		var insize = 1, nmerges, psize = 0, qsize = 0; | ||||
| 		var p, q, e, tail:MainEvent; | ||||
|  | ||||
| 		while (true) { | ||||
| 			p = list; | ||||
| 			list = null; | ||||
| 			tail = null; | ||||
| 			nmerges = 0; | ||||
| 			while (p != null) { | ||||
| 				nmerges++; | ||||
| 				q = p; | ||||
| 				psize = 0; | ||||
| 				for (i in 0...insize) { | ||||
| 					psize++; | ||||
| 					q = q.next; | ||||
| 					if (q == null) | ||||
| 						break; | ||||
| 				} | ||||
| 				qsize = insize; | ||||
| 				while (psize > 0 || (qsize > 0 && q != null)) { | ||||
| 					if (psize == 0) { | ||||
| 						e = q; | ||||
| 						q = q.next; | ||||
| 						qsize--; | ||||
| 					} else if (qsize == 0 | ||||
| 						|| q == null | ||||
| 						|| (p.priority > q.priority || (p.priority == q.priority && p.nextRun <= q.nextRun))) { | ||||
| 						e = p; | ||||
| 						p = p.next; | ||||
| 						psize--; | ||||
| 					} else { | ||||
| 						e = q; | ||||
| 						q = q.next; | ||||
| 						qsize--; | ||||
| 					} | ||||
| 					if (tail != null) | ||||
| 						tail.next = e; | ||||
| 					else | ||||
| 						list = e; | ||||
| 					e.prev = tail; | ||||
| 					tail = e; | ||||
| 				} | ||||
| 				p = q; | ||||
| 			} | ||||
| 			tail.next = null; | ||||
| 			if (nmerges <= 1) | ||||
| 				break; | ||||
| 			insize *= 2; | ||||
| 		} | ||||
| 		list.prev = null; // not cycling | ||||
| 		pending = list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 		Run the pending events. Return the time for next event. | ||||
| 	**/ | ||||
| 	static function tick() { | ||||
| 		sortEvents(); | ||||
| 		var e = pending; | ||||
| 		var now = haxe.Timer.stamp(); | ||||
| 		var wait = 1e9; | ||||
| 		while (e != null) { | ||||
| 			var next = e.next; | ||||
| 			var wt = e.nextRun - now; | ||||
| 			if (wt <= 0) { | ||||
| 				wait = 0; | ||||
| 				e.call(); | ||||
| 			} else if (wait > wt) | ||||
| 				wait = wt; | ||||
| 			e = next; | ||||
| 		} | ||||
| 		return wait; | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user