lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

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: ObjC_classic/Classes/NSThread.html

It goes something like this:

-- Assume some 'long' running object
local aConvolutedObject =

-- The 'magic' incarnation
local aTask = aConvolutedObject, aConvolutedObject.doIt() )

-- Run the task

A LUTask provides a couple of public methods to access the standard coroutine functionalities:


As well as accessor methods to what underlying LUObject and method the task is running:

-- returns the underlying object this task is wrapped around

-- returns the underlying method that will be execute

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
	    self.class().register( self )

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() )

    return ivars.routine

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 )

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


    -- do some more stuff


    -- be done with it

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 )

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 at the end of the return statement

	    return coroutine.yield( self.routine() ), self.class().run()

    return nil

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!


PA, Onnay Equitursay

Attachment: LUObject.lua
Description: Binary data

Attachment: LUTask.lua
Description: Binary data

Attachment: LUList.lua
Description: Binary data