{ Coroutine support class
Note: recursive calling the same instance of the coroutine not supported
Note: not threadsafe
Note: no thread affinity
}

TCoroutine = class
private

{We are abusing a thread here for several reasons.
a. To have windows create a stack with a default size, and guardpages and all that
b. To have windows create a SEH base
c. To have delphi create a delphi exception handler base
The thread itself will do nothing, we steal
its stack and let it block on a mutex till the Coroutine is released. Setting up these parameters
ourself is possible but this is much simpler.
Letting the thread block on a mutex should cost no measurable amount of overhead.
}

procedure StealThread;
procedure Setup;
procedure Reset;
procedure BackToCaller;
procedure Enter;
protected
procedure Yield; // call me from the Execute method to return the thread to
// the call of Invoke, unless IsTerminating is true then an exception
// is raised
function IsTerminating: Boolean; // signal to Execute that it should not call
// Yield and that it should cleanup its resources and return
// from the method
procedure Execute; virtual; abstract; // override me, either return // from this method or call yield
public
constructor Create;
{
Destruction:
If the Coroutine is currently active then:
IsTerminating is set to true
Then Invoke is called and we want the Execute method to return
Yield throws an exception to enforce this.
}
destructor Destroy; override;
procedure Invoke; //call me to run/continue the Execute method
end;