193 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
/*
 | 
						|
 * 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 haxe;
 | 
						|
 | 
						|
#if (target.threaded && !cppia)
 | 
						|
import sys.thread.Thread;
 | 
						|
import sys.thread.EventLoop;
 | 
						|
#end
 | 
						|
 | 
						|
/**
 | 
						|
	The `Timer` class allows you to create asynchronous timers on platforms that
 | 
						|
	support events.
 | 
						|
 | 
						|
	The intended usage is to create an instance of the `Timer` class with a given
 | 
						|
	interval, set its `run()` method to a custom function to be invoked and
 | 
						|
	eventually call `stop()` to stop the `Timer`.
 | 
						|
 | 
						|
	Note that a running `Timer` may or may not prevent the program to exit
 | 
						|
	automatically when `main()` returns.
 | 
						|
 | 
						|
	It is also possible to extend this class and override its `run()` method in
 | 
						|
	the child class.
 | 
						|
**/
 | 
						|
class Timer {
 | 
						|
	#if (flash || js)
 | 
						|
	private var id:Null<Int>;
 | 
						|
	#elseif (target.threaded && !cppia)
 | 
						|
	var thread:Thread;
 | 
						|
	var eventHandler:EventHandler;
 | 
						|
	#else
 | 
						|
	private var event:MainLoop.MainEvent;
 | 
						|
	#end
 | 
						|
 | 
						|
	/**
 | 
						|
		Creates a new timer that will run every `time_ms` milliseconds.
 | 
						|
 | 
						|
		After creating the Timer instance, it calls `this.run` repeatedly,
 | 
						|
		with delays of `time_ms` milliseconds, until `this.stop` is called.
 | 
						|
 | 
						|
		The first invocation occurs after `time_ms` milliseconds, not
 | 
						|
		immediately.
 | 
						|
 | 
						|
		The accuracy of this may be platform-dependent.
 | 
						|
	**/
 | 
						|
	public function new(time_ms:Int) {
 | 
						|
		#if flash
 | 
						|
		var me = this;
 | 
						|
		id = untyped __global__["flash.utils.setInterval"](function() {
 | 
						|
			me.run();
 | 
						|
		}, time_ms);
 | 
						|
		#elseif js
 | 
						|
		var me = this;
 | 
						|
		id = untyped setInterval(function() me.run(), time_ms);
 | 
						|
		#elseif (target.threaded && !cppia)
 | 
						|
		thread = Thread.current();
 | 
						|
		eventHandler = thread.events.repeat(() -> this.run(), time_ms);
 | 
						|
		#else
 | 
						|
		var dt = time_ms / 1000;
 | 
						|
		event = MainLoop.add(function() {
 | 
						|
			@:privateAccess event.nextRun += dt;
 | 
						|
			run();
 | 
						|
		});
 | 
						|
		event.delay(dt);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Stops `this` Timer.
 | 
						|
 | 
						|
		After calling this method, no additional invocations of `this.run`
 | 
						|
		will occur.
 | 
						|
 | 
						|
		It is not possible to restart `this` Timer once stopped.
 | 
						|
	**/
 | 
						|
	public function stop() {
 | 
						|
		#if (flash || js)
 | 
						|
		if (id == null)
 | 
						|
			return;
 | 
						|
		#if flash
 | 
						|
		untyped __global__["flash.utils.clearInterval"](id);
 | 
						|
		#elseif js
 | 
						|
		untyped clearInterval(id);
 | 
						|
		#end
 | 
						|
		id = null;
 | 
						|
		#elseif (target.threaded && !cppia)
 | 
						|
		thread.events.cancel(eventHandler);
 | 
						|
		#else
 | 
						|
		if (event != null) {
 | 
						|
			event.stop();
 | 
						|
			event = null;
 | 
						|
		}
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		This method is invoked repeatedly on `this` Timer.
 | 
						|
 | 
						|
		It can be overridden in a subclass, or rebound directly to a custom
 | 
						|
		function:
 | 
						|
 | 
						|
		```haxe
 | 
						|
		var timer = new haxe.Timer(1000); // 1000ms delay
 | 
						|
		timer.run = function() { ... }
 | 
						|
		```
 | 
						|
 | 
						|
		Once bound, it can still be rebound to different functions until `this`
 | 
						|
		Timer is stopped through a call to `this.stop`.
 | 
						|
	**/
 | 
						|
	public dynamic function run() {}
 | 
						|
 | 
						|
	/**
 | 
						|
		Invokes `f` after `time_ms` milliseconds.
 | 
						|
 | 
						|
		This is a convenience function for creating a new Timer instance with
 | 
						|
		`time_ms` as argument, binding its `run()` method to `f` and then stopping
 | 
						|
		`this` Timer upon the first invocation.
 | 
						|
 | 
						|
		If `f` is `null`, the result is unspecified.
 | 
						|
	**/
 | 
						|
	public static function delay(f:Void->Void, time_ms:Int) {
 | 
						|
		var t = new haxe.Timer(time_ms);
 | 
						|
		t.run = function() {
 | 
						|
			t.stop();
 | 
						|
			f();
 | 
						|
		};
 | 
						|
		return t;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Measures the time it takes to execute `f`, in seconds with fractions.
 | 
						|
 | 
						|
		This is a convenience function for calculating the difference between
 | 
						|
		`Timer.stamp()` before and after the invocation of `f`.
 | 
						|
 | 
						|
		The difference is passed as argument to `Log.trace()`, with `"s"` appended
 | 
						|
		to denote the unit. The optional `pos` argument is passed through.
 | 
						|
 | 
						|
		If `f` is `null`, the result is unspecified.
 | 
						|
	**/
 | 
						|
	public static function measure<T>(f:Void->T, ?pos:PosInfos):T {
 | 
						|
		var t0 = stamp();
 | 
						|
		var r = f();
 | 
						|
		Log.trace((stamp() - t0) + "s", pos);
 | 
						|
		return r;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Returns a timestamp, in seconds with fractions.
 | 
						|
 | 
						|
		The value itself might differ depending on platforms, only differences
 | 
						|
		between two values make sense.
 | 
						|
	**/
 | 
						|
	public static inline function stamp():Float {
 | 
						|
		#if flash
 | 
						|
		return flash.Lib.getTimer() / 1000;
 | 
						|
		#elseif js
 | 
						|
		#if nodejs
 | 
						|
		var hrtime = js.Syntax.code('process.hrtime()'); // [seconds, remaining nanoseconds]
 | 
						|
		return hrtime[0] + hrtime[1] / 1e9;
 | 
						|
		#else
 | 
						|
		return @:privateAccess HxOverrides.now() / 1000;
 | 
						|
		#end
 | 
						|
		#elseif cpp
 | 
						|
		return untyped __global__.__time_stamp();
 | 
						|
		#elseif python
 | 
						|
		return Sys.cpuTime();
 | 
						|
		#elseif sys
 | 
						|
		return Sys.time();
 | 
						|
		#else
 | 
						|
		return 0;
 | 
						|
		#end
 | 
						|
	}
 | 
						|
} |