lua-users home
lua-l archive

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



I am playing with the lua vm in the browser [1]. Both browser and lua have a collaborative multitasking design, so I would like to use coroutine for the interaction.

The whole lua script is wrapped in a coroutine, and the browser resume it until it goes to the 'dead' state. Ideally I can wrap browser actions in some lua function that yields. On the _javascript_ side there will be something that parses the yielded values.

This does not works when the "Browser interaction api" is called from a sub-coroutine created in the lua code. Or, at least, I need to propagate the "Yielding" to the parent coroutine, and the "Resuming" to the child one [2].

Obviously, to make this 'Deep yielding/resuming' as much transparent as possible, I have to replace coroutine.resume and friends. So I ask:

Am I missing something? Is there some simpler solution?

It seems to me a quite natural scenario for a coroutine, also in a non-browser environment...

pocomane

[1] https://github.com/pocomane/walua
[2] I.e. I need something like the follolwing prototype code :

```
-- Nested Coroutine

local THREAD = 1
local SUCCESS = 2
local TARGET = 3
local PARENT = 4

local nccurrent = nil

local function nccreate(f)
  local nc = {0,0,0,0}
  nc[THREAD] = coroutine.create(f)
  return nc
end

local function ncyield(nc, ...)
  nc[TARGET] = nc[THREAD]
  return coroutine.yield(nc, ...)
end

local function ncresume(nc, ...)
  nc[PARENT] = nccurrent
  nccurrent = nc
  return (function(a, b, ...)
      nc[SUCCESS] = a
      if coroutine.status(nc[THREAD]) ~= 'suspended' then
        return b, ...
      end
      if nc == b then
          b = nil
      end
      nc[TARGET] = b
      if nc[PARENT] == nil then
        return b, ...
      else
        return coroutine.yield(b, ...)
      end
  end)(coroutine.resume(nc[THREAD], ...))
end
``

Usage example:

```
local top, middle, bottom
local out = ''

out = out .. 'a'

top = nccreate(function()
  out = out .. 'b'
  
  middle = nccreate(function()
    out = out .. 'c'
    
    bottom = nccreate(function()
        out = out .. 'd'
        
        ncyield(middle)
        
        out = out .. '-UNREACHED-'
    end)
    ncresume(bottom)
    
    out = out .. '-UNREACHED-'
  end)
  ncresume(middle)
  
  out = out .. 'f'
end)
ncresume(top)

out = out .. 'e'
ncresume(top)

assert(out=='abcdef')
```

A production code should handle several cases (e.g. errors) and I am a bit unsure about its performance.