Last active
May 17, 2018 19:02
-
-
Save Corecii/4a58afacf1352a390889d24fd6c98f54 to your computer and use it in GitHub Desktop.
Untested example code for reusing lanes in luajit to bypass thread creation time
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
local retired_lanes = {} | |
local function thread_func(controller) | |
while true do | |
local key, func_args = controller:receive(10, "func_args") | |
if key == lanes.cancel_error then | |
break | |
end | |
if func_args then | |
local func = func_args.func | |
local args = func_args.args | |
local results = {func(unpack(args))} | |
controller:send("results", results) | |
end | |
end | |
end | |
local function run_lane(func, ...) | |
-- get a lane | |
local lane_info | |
if #retired_lanes > 0 then | |
-- use an existing one that isn't running anything | |
lane_info = retired_lanes[#retired_lanes] | |
retired_lanes[#retired_lanes] = nil | |
else | |
-- there are no existing ones; make a new one | |
local controller = lanes.linda("threads_controller") | |
local lane = lanes.gen(thread_func, controller) | |
lane_info = { | |
lane = lane, | |
controller = controller | |
} | |
end | |
-- set up last_results | |
local run_results = { | |
results = nil, | |
controller = lane_info.controller, | |
lane_info = lane_info | |
} | |
function run_results:receive(timeout) | |
if self.results then | |
return true, unpack(self.results) | |
end | |
local key, results = self.controller:receive(timeout, "results") | |
if key == lanes.cancel_error then | |
return false, nil | |
elseif not results then | |
return nil, nil | |
end | |
-- save the results, then make the lane re-usable by putting it in retired_lanes | |
self.results = results | |
retired_lanes[#retired_lanes + 1] = self.lane_info | |
return true, unpack(results) | |
end | |
function run_results:get() | |
if self.results then | |
return true, unpack(self.results) | |
end | |
local results = self.controller:get("results") | |
if results == lanes.cancel_error then | |
return false, nil | |
elseif not results then | |
return nil, nil | |
end | |
-- save the results, then make the lane re-usable by putting it in retired_lanes | |
self.results = results | |
retired_lanes[#retired_lanes + 1] = self.lane_info | |
return true, unpack(results) | |
end | |
lane_info.last_results = run_results | |
-- run the lane | |
local success = lane_info.controller:send("func_args", {func = func, args = {...}}) | |
if success == lanes.cancel_error then | |
-- if it's cancelled, we need to not use it again and get a new lane | |
return false | |
else | |
return true, run_results | |
end | |
end | |
local function run_thread(func, ...) | |
local success, results | |
while not success do | |
success, results = run_lane(func, ...) | |
end | |
return results | |
end | |
--- | |
-- example: | |
local results = run_thread(function(...) | |
print(...) | |
local a = 5 | |
for _ = 1, 100000000 do | |
a = a + 2 | |
end | |
return a, "hello!" | |
end, 1, 2, 3) | |
local success, computation_result, message = results:receive(5) | |
if success == false then | |
print("thread run failed! (cancelled?)") | |
elseif success == nil then | |
print("thread is not finished yet!") | |
else | |
print("thread finished! result: "..tostring(computation_result).." "..tostring(message)) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment