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).
Related
A simple example:
coroutine.resume(coroutine.create(function()
print(debug.traceback())
end))
print(debug.traceback())
the output:
stack traceback:
./v.lua:2: in function <./v.lua:1>
stack traceback:
./v.lua:4: in main chunk
[C]: in ?
It shows that traceback inside a coroutine doesn't know about how it is resumed, so that xxx: in main chunk doesn't show.
How can I get the complete stacktrace inside a coroutine?
Well, I found a workaround here.
Since one Lua VM has only one execution point at one time (and that's why a full call stack is there), we can record resumption information manually.
In lua, manually build a resume-stack trace.
local xresume = coroutine.resume
local xtrace = debug.traceback
-- magic here! Take care of main thread.
local mainthr = coroutine.running() -- captureing is a must.
debug.traceback = function(athr)
if athr then return xtrace(athr) end -- no interest in specified thread.
return xtrace(mainthr)
end
coroutine.resume = function(thr, ...)
-- another magic.
local uptrace = debug.traceback
debug.traceback = function(athr)
if athr then return xtrace(athr) end -- no interest in specified thread.
return xtrace(thr) -- trace the stack of thr.
.. '\n' .. uptrace() -- trace from thr's resume point.
end
local result = { xresume(thr, ...) }
debug.traceback = uptrace
return table.unpack(result)
end
Other tips:
Using global table to store threads also works. But you still need to capture main thread so that it can be traced everywhere.
Writing codes in C function can prevent traceback into hooked coroutine.resume and debug.traceback itself, give you a clearer output.
You won't get much performance hit when debug.traceback is not called.
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.
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 have a custom Lua interpreter executable with some basic socket functionality built in. It's not Luasocket, and as much as I would like to be using Luasocket here, I can't (so please don't suggest it as an answer).
The socket API that I'm working with relies on asynchronous closures to signal that a network operation is complete. So, in the code below, socketConnect() returns immediately and then onConnect() is called later on when the connection is complete.
local function onConnect(cookie, err, sock)
print("Connected!")
end
local function connect(host, port)
local success, err = socketConnect(host, port, onConnect)
print("Connecting...")
end
So, here's the question. I want to make the connect() function block until the onConnect() closure is called. I'm pretty new at Lua, but I'm hoping that coroutines might be helpful here?
EDIT: Here's my attempt at making the function block by using a coroutine:
local connected = false
local function onConnect(cookie, err, sock)
print("Connected!")
connected = true
end
local coroConnect = coroutine.create(
function()
local success, err = socketConnect(m_sHost, m_nPort, onConnect);
while not connected do
coroutine.yield()
end
end
)
local function connect(sHost, nPort)
m_sHost = sHost
m_nPort = nPort
while not coroutine.status(coroConnect) ~= "dead" do
coroutine.resume(coroConnect)
print("Connecting...")
end
end
If you want to use coroutines, something along these lines may work for you (or give you an idea on what to try):
-- this should really be a socket property, but good enough for this example
local connected
local function onConnect(cookie, err, sock)
print("Connected!")
connected = true
end
local function connect(host, port)
connected = false
local success, err = socketConnect(host, port, onConnect)
while not connected do
coroutine.yield()
end
print("Connecting...")
end
If you now create a coroutine from connect function and continue calling that coroutine with coroutine.resume until it's completed (coroutine.status for that coroutine will return 'dead'), you will get the desired result. Obviously, you can move that while loop into socketConnect function itself, which will make is synchronous from the user perspective as it won't return anything until onConnect is executed.