Skip to content

Instantly share code, notes, and snippets.

@Corecii
Last active May 17, 2018 19:02
Show Gist options
  • Save Corecii/4a58afacf1352a390889d24fd6c98f54 to your computer and use it in GitHub Desktop.
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
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