Last active
July 5, 2016 21:39
-
-
Save bassosimone/7121899bba4fad0928c18e3ee3b905e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mk_runtime = (function () | |
local self = {} | |
self.coroutines = {} | |
self.async = function (func) | |
self.coroutines[coroutine.create(func)] = { | |
status = "running", | |
func = func | |
} | |
end | |
self.suspend = function () | |
coro, _ = coroutine.running() | |
self.coroutines[coro].status = "suspended" | |
--[[ | |
Here: pass to C++ coroutine and arguments, then C++ does: | |
1. unmarshalling of coroutine and arguments from the stack | |
2. call_soon | |
3. the call_soon would then call the real function | |
4. whose callback would marshal results | |
5. store them on the coroutine record | |
6. set coroutine status again as running | |
]] | |
print("suspend", coro) | |
coroutine.yield() | |
-- Here we read the result from coroutine record and return it | |
end | |
-- This is not actually needed when the coroutine would be resume | |
-- by C/C++ code as was described above | |
self.resume_all = function () | |
for coro, record in pairs(self.coroutines) do | |
if record.status == "suspended" then | |
record.status = "running" | |
print("resume", coro) | |
end | |
end | |
end | |
self.loop = function () | |
repeat | |
local new_running = {} | |
local count = 0 | |
for coro, record in pairs(self.coroutines) do | |
if record.status == "running" then | |
coroutine.resume(coro) | |
if coroutine.status(coro) ~= "dead" then | |
new_running[coro] = record | |
count = count + 1 | |
end | |
end | |
end | |
self.running = new_running | |
until count <= 0 | |
end | |
return self | |
end)() | |
-- Shows that use can used nested coroutines without harm if you wish | |
local gimme_antani = coroutine.wrap(function () | |
while (true) do | |
coroutine.yield("antani...") | |
end | |
end) | |
function antani() | |
print("i want antani...") | |
print(gimme_antani()) | |
print("i got antani...") | |
-- This is the point where we emulate a sync function in lua triggering | |
-- async behavior in C++. This should instead be something like: | |
-- `local result = dns_query( ... )` | |
local result = mk_runtime.suspend({ | |
"dns_query", "IN", "A", "www.google.com", { | |
["dns/nameserver"] = "8.8.8.8" | |
} | |
}) | |
coroutine.yield() | |
end | |
mk_runtime.async(function () | |
for _ = 1, 1024 do | |
antani() | |
end | |
end) | |
mk_runtime.async(function () | |
for _ = 1, 6 do | |
print("second coroutine") | |
coroutine.yield() | |
end | |
print("before resume") | |
-- This is here to resume because resume in C++ is not yet implemented | |
mk_runtime.resume_all() | |
print("after resume") | |
end) | |
mk_runtime.async(function () | |
print ("aaa") | |
coroutine.yield() | |
end) | |
-- Emulates the MK loop that runs forever | |
mk_runtime.async(function () | |
while (true) do | |
coroutine.yield() | |
end | |
end) | |
mk_runtime.loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment