Reputation: 97
I want to figure out a way to create an object by passing a function into it, having it be sent to a coroutine, then have a few function such as start() stop() and status() It could look like this, but i don't know how to implement this.
local Process = {}
Process.__index = Process
function newProcess(name,func)
local self = setmetatable({}, Process)
self.name = name
self.func = func
return self
end
This would just make the initialization for the process, by passing a name and function. I would like to add some methods too, below. (this is where i need help implementing)
function Process:start()
self.thread = -- create coroutine here
self.thread -- Resume the coroutine here
end
Creates a coroutine with the function variable "self.func" Then starts the coroutine. I have the initialization in the start function so it can be run multiple times. This is where i am having trouble
function Process:stop()
-- Stops the running coroutine (shutdown or in case i need to end i)
end
I may need this greatly in the future but i have no idea how to implement it. Basically use the self.thread variable created above
function Process:status()
-- Maybe return the coroutine.status?
end
Thank you for your help. Thanks!
Upvotes: 2
Views: 369
Reputation: 29483
You are very close. Coroutines are cooperative threads, so the function you pass to process will have to call coroutine.yield (ideally, often). Also Process needs resume() so the "thread" can do more work. The coroutine can be stopped anytime from outside the coroutine while not executing the coroutine: just don't resume it, and nil it. It can be stopped anytime from within the coroutine by not yielding but returning. It would look something like this (not tested for bugs):
function Process:start()
self.thread = coroutine.create(self.func)
self:resume() -- run to next yield
end
function Process:resume()
coroutine.resume(self.thread)
end
function Process:stop() -- from "outside" thread
self.thread = nil
end
function Process:status()
return coroutine.status(self.thread)
end
Make sure you look at Lua ref manual sections 2.11 for example of how to structure your function using coroutine.yield, and section 5.2 for details on coroutine module.
You could have multiple threads:
function func1() ... end
function func2() ... end
p1 = newProcess("func1", func1)
p2 = newProcess("func2", func2)
p1:start() -- runs func1 to its first yield
p2:start() -- runs func2 to its first yield
p1:resume() -- runs func1 to its second yield
p2:resume() -- runs func2 to its second yield
Note that the above will not work if you have func1 as such:
function func1()
sleep(100) -- seconds
end
But it will work if func1 is this:
function func1()
for i=1,100 do
sleep(1)
coroutine.yield()
end
end
Both sleep the same amount of time (100 s) but the first version will return only after 100 s, whereas the second one can be called 100 times, which gives the same results as single core multiple threads. Note: sleep is pseudocode, it is not available in Lua; and sleep is only used to illustrate a function that takes a large amount of time to do something that can broken down into many little chunks.
Upvotes: 2
Reputation: 69934
You can't do that, since coroutines are a form of cooperative multitasking. This means that only one coroutine is running each time and that the only way to transfer control back from the running coroutine is for the coroutine itself to yield
at an appropriate point.
Upvotes: 0