I am trying to implement multitasking to lua, so that I can use multiple Threads on the Node MCU.
My idea was to run the threads as functions, pause them and continue with the next and do that in a loop. The debug.sethook function seemed prommising but didn't work with the corutines, they executed the hook only after the corutine finished.
I only really need a way to pause a functon.
mt = {}
mt.threadList = {}
function mt.newThread(fnc)
table.insert(mt.threadList,fnc)
end
function mt.update()
for i=1,#mt.threadList do
print("EPOCH: "..i)
debug.sethook(print,"c",40)
coroutine.resume( mt.threadList[i] )
debug.sethook()
end
end
function tA()
for i=1,100 do
print("A",i)
end
end
function tB()
for i=1,100 do
print("B",i)
end
end
mt.newThread(tA)
mt.newThread(tB)
mt.update()
coroutine.resume continues a coroutine, not a regular function. Coroutines (from the Lua side) are generated by coroutine.create. coroutine.resume can only be called on the value returned by coroutine.create.
That being said, Lua coroutines are cooperative (hence the term "co-routine"). That means that you're not supposed to be able to arbitrarily interrupt their execution at any particular point. The coroutine itself should decide when to suspend, via a call to coroutine.yield or similar functions.
You can use debug.sethook on a coroutine to set its debug hook (if you don't pass a coroutine to sethook, then it assumes that you're setting the debug hook for the current thread, which is not what you want), and thereby coroutine.yield at arbitrary points in time. But you really shouldn't.
In any case, without coroutines, there is no way to "pause" a function's execution at all. Not even with a debug hook.
Related
What I want to do is to dynamically stop a function in lua. My code that i tried:
local SaveReal = Thread
local stopped = false
--[[
Thread function runs the lua function
that it includes in a separate thread.
It was created before here
and is trying to be manipulated here.
]]--
Thread = function(func)
SaveReal(function()
while(not stopped) do
func()
end
end)
end
Thread(function()
while(true) do
print("Thread working")
end
end)
Maybe if I could read the contents of the function as a string, I could load it into my manipulative function with load. so the code would not work if my flag is not false.
Lua has something called Coroutines to provide multi-tasking (not multi-threading).
I'm trying to create a dispatcher which schedules multiple coroutines. The dispatcher needs to pause the coroutine, I can't figure out how to do this.
Update
Instead of kill, I meant to pause the coroutine from the outside.
You can kill a coroutine by setting a debug hook on it that calls error() from that hook. The next time the hook is called, it will trigger error() call, which will abort the coroutine:
local co = coroutine.create(function()
while true do print(coroutine.yield()) end
end)
coroutine.resume(co, 1)
coroutine.resume(co, 2)
debug.sethook(co, function()error("almost dead")end, "l")
print(coroutine.resume(co, 3))
print(coroutine.status(co))
This prints:
2
3
false coro-kill.lua:6: almost dead
dead
library that will yield when you return true in the hook that been set with debug.sethook(co, function() return true end, "y")
the library is enough to create multitask lua system just run require("yieldhook") at very first of your code further info at the git
https://github.com/evg-zhabotinsky/yieldhook
use coroutine.yield(coroutine-you-want-to-pause)
I have the following lua script :
mydata={}
function update(val)
mydata["x"] = val
if (val == 10)
-- Call C-Api(1)
else
--Register callback with C when free or some event happens
register_callback(callme)
end
function callme()
end
Basically I would like to have two instances of this script running in my C program/process with out having to create a new LUA state per script. And I want to call the function update() with val = 10 from the one instance and call the function update() with val = 20 from another instance. From the second instance it registers a callback function and just waits to be called.
Basically the script file is kind of a RULE that i am trying to achieve.
Several events on the system can trigger this rule or script file. I would like to process this rule as per the event that triggered it. There could be multiple events triggering this script to run at the same time. So I need to have multiple instances of this script running differentiated by the kind of event that triggered it.
To Summarize, I want each caller to have separate individual instance of mydata
I would like to achieve something like this. I read some where that we should be able to run multiple instances of a lua script with out having to create a new lua instance by loading a new environment before loading the script
But I am not able to find the exact details.
Could some body help ?
While I'm still not sure what exactly you are trying to achieve, but if you want to have two instances of the same function that keep the data they use private, you just need to create a closure and return an anonymous function that your C code will use.
Something like this should work:
function createenv(callme)
local mydata={}
return function (val) -- return anonymous function
mydata["x"] = val
if (val == 10)
-- Call C-Api(1)
else
--Register callback with C when free or some event happens
register_callback(callme)
end
end
end
Now in one part of your (C or Lua) code you can do:
local update = createenv(function() --[[do whatever]] end)
update(10)
And then in another part you can do:
local update = createenv(function() --[[do something else]] end)
update(20)
And they should have nothing in common between each other. Note that they still shared the same Lua state, but their instances of mydata will be independent of each other.
I want to exit execution of Lua script on some condition .
Example :
content = get_content()
if not content then
-- ( Here i want some kind of exit function )
next_content = get_content()
--example there can lot of further checks
Here I want that if I am not getting content my script suppose to terminate is should not go to check to next.
Use os.exit() or just return from some "main" function if your script is embedded.
os.exit()
kill process by sending a signal
do return end
stop execution
The two methods are not equal if you want to write and execute some luacode in the interpreter after stopping the execution by launching your program using the -i flag.
th -i main.lua
extract from the lua api doc :
For syntactic reasons, a break or return can appear only as the last statement of a block (in other words, as the last statement in your chunk or just before an end, an else, or an until). For instance, in the next example, break is the last statement of the then block.
local i = 1
while a[i] do
if a[i] == v then break end
i = i + 1
end
Usually, these are the places where we use these statements, because any other statement following them is unreachable. Sometimes, however, it may be useful to write a return (or a break) in the middle of a block; for instance, if you are debugging a function and want to avoid its execution. In such cases, you can use an explicit do block around the statement:
function foo ()
return --<< SYNTAX ERROR
-- `return' is the last statement in the next block
do return end -- OK
... -- statements not reached
end
In lua 5.2.0-beta-rc1+, you can add a label at the end of your code called ::exit:: or something of the like, and then whenever you need to exit the program just call it like this:
goto exit
If I want to always send an event to the initial state of a gen_fsm when I have spawned it, where should I put that function call? Right after start_link or from the process that invoked start_link in the first place. Are there any best practices here?
If you just want to alter the state of the FSM after you start it, you might simply implement the init function for your state machine:
Reading from: http://www.erlang.org/doc/man/gen_fsm.html#Module:init-1
Whenever a gen_fsm is started using
gen_fsm:start/3,4 or
gen_fsm:start_link/3,4, this function
is called by the new process to
initialize.
Args is the Args argument provided to
the start function.
If initialization is successful, the
function should return
{ok,StateName,StateData},
{ok,StateName,StateData,Timeout} or
{ok,StateName,StateData,hibernate},
where StateName is the initial state
name and StateData the initial state
data of the gen_fsm.
Also, using the init function, you're sure about the atomicity of the two functions (start_link and init). They will both succeed or fail.
I thik it is right to send first event from the process invoking FSM start function. Or return timeout = 0 from init/1 and handle 'timeout' event in the initial state.
On the other hand, it makes races possible if your gen_fsm is a rgistered process. If that is the case I would send message to the gen_fsm process PID from init/1 befor registering.