module coneneko.fiber;
import sdl;
version (D_Version2) {}
else
{
import std.thread;

/**
FiberのようなThread、推奨しません。
待ち時間が少なくなるように処理を先行させているため、
複数のFiberを作って平行して処理する場合に同期がとれない場合があります。
**/
class Fiber // TODO 2.0 phobosが対応しているので不要になったら削除
{
	private Thread thread;
	private bool resting = false;
	static Uint32 timeoutSpan = 10; /// >= 2 millisecond
	
	invariant()
	{
		assert(timeoutSpan >= 2);
	}
	
	///
	this()
	{
		thread = new Thread(&run);
		thread.start();
	}
	
	void yield() ///
	{
		resting = true;
		while (resting) SDL_Delay(1);
	}
	
	void opCall() /// 進む、timeoutSpan以上の反応がない場合はそのまま返ります
	{
		if (terminated) throw new Error("Fiber.opCall terminated");
		auto baseTime = SDL_GetTicks();
		while (!resting)
		{
			auto t = SDL_GetTicks() - baseTime; // ループに入ってから経過した時間
			if (timeoutSpan / 2 < t) thread.resume; // gcで停止の可能性
			if (timeoutSpan < t) return; // timeout
			Thread.yield();
		}
		resting = false;
	}
	
	bool terminated() ///
	{
		return thread.getState() == Thread.TS.TERMINATED;
	}
	
	abstract int run(); ///
}

} // version (D_Version2) {} else {
