|
|
||
|
On Jan 29, 2005, at 18:41, André Carregal wrote:
PS I struggle with co-routines.Doesn't everyone? :o)
Well, here we go again, my first foolish attempt to make sense of this new Wonderland. I really do feel like Alice though. Or was it Dorothy? One way or another, we are not in Kansas anymore!
Anyhow, I tried to wrap this coroutine business with something more or less semantically equivalent to NSThread +detachNewThreadSelector:toTarget:withObject:
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ ObjC_classic/Classes/NSThread.html
It goes something like this: -- Assume some 'long' running object local aConvolutedObject = ConvolutedObject.new() -- The 'magic' incarnation local aTask = LUTask.new( aConvolutedObject, aConvolutedObject.doIt() ) -- Run the task aTask.run()A LUTask provides a couple of public methods to access the standard coroutine functionalities:
aTask.status() aTask.resume() aTask.yield()As well as accessor methods to what underlying LUObject and method the task is running:
-- returns the underlying object this task is wrapped around aTask.object() -- returns the underlying method that will be execute aTask.method() The 'magic' happens in the "run" method:-- instance method to 'run' the routine by registering it with the class run loop
local run = function()
if not ivars.routine then
routine()
self.class().register( self )
end
end
First, the method check if it was run already or not. Then, if this is
the first time, it register itself with the class run loop.
The private 'routine' method creates the 'coroutine' itself:
-- private method to wrap ivars.method in a coroutine
local routine = function()
if not ivars.routine then
ivars.routine = coroutine.create( self.method() )
end
return ivars.routine
end
Then the task is passed on to LUTask.register():
-- class method to register a task with the run loop
local register = function( aTask )
if aTask then
aTask.object().setTask( aTask )
tasks().add( aTask )
run()
end
end
LUTask.register() simply adds the given task to its list and set it as
the current task of the underlying object:
aTask.object().setTask( aTask )This allows any LUObject to access their current 'task' when their coroutine method is invoked:
local doIt()
-- do stuff
this.task().yield()
-- do some more stuff
this.task().yield()
-- be done with it
end
Finally, LUTask.register() kicks in the run loop itself:
-- class method to 'run' through all the tasks
local run = function()
local someTasks = tasks()
if someTasks then
local count = someTasks.size()
if count > 0 then
for index = 1, count do
local aTask = someTasks.get(
index )
local aStatus = aTask.status()
if aStatus == "dead" then
aTask.object().setTask(
nil )
someTasks.remove( index
)
else
aTask.resume()
end
end
end
end
end
The run loop goes through the list of tasks and check their status. If
a task is 'dead' (ie finished), it removes it from its list. Otherwise,
it invokes its resume() method.
The run loop runs only once through the list... this is somewhat on purpose... as I would like to avoid the run loop "busy waiting" on something to execute even when strictly nothing is going on at all... ideally I would like to have some sort of "event" driven system... but I have no idea how to do that yet... instead the run loop "rewind" itself by somehow (ab)using recursion... the "rewinding" is driven by the objects being executed... each time an object interacts with its task, the run loop gets automatically "rewinded":
-- instance method to yield the routine
local yield = function()
if ivars.routine then
-- note the additional call to LUTask.run() at the end of the
return statement
return coroutine.yield( self.routine() ), self.class().run()
end
return nil
end
Not sure if any of this will fly in practice as I even tested this
concoction yet :))
See attachment for the current draft implementation. Feedbacks and head slapping very much welcome! Cheers -- PA, Onnay Equitursay http://alt.textdrive.com/
Attachment:
LUObject.lua
Description: Binary data
Attachment:
LUTask.lua
Description: Binary data
Attachment:
LUList.lua
Description: Binary data