Skip to content

Commit

Permalink
Use native (x)pcall if possible.
Browse files Browse the repository at this point in the history
Delegate to native (x)pcall if co(x)pcall is called from the main thread
where yielding isn't allowed anyway. This reduces the runtime by more
than 50% in this very common case.
  • Loading branch information
siffiejoe committed Feb 22, 2016
1 parent df52b7f commit 66f0ee6
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions src/coxpcall.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ end
-- Implements xpcall with coroutines
-------------------------------------------------------------------------------
local performResume, handleReturnValue
local oldpcall = pcall
local oldpcall, oldxpcall = pcall, xpcall
local pack = table.pack or function(...) return {n = select("#", ...), ...} end
local unpack = table.unpack or unpack
local running = coroutine.running
local coromap = setmetatable({}, { __mode = "k" })

function handleReturnValue(err, co, status, ...)
if not status then
return false, err(debug.traceback(co, (...)), ...)
Expand All @@ -57,15 +57,32 @@ function performResume(err, co, ...)
return handleReturnValue(err, co, coroutine.resume(co, ...))
end

local function id(trace, ...)
return trace
end

function coxpcall(f, err, ...)
local res, co = oldpcall(coroutine.create, f)
if not res then
local params = pack(...)
local newf = function() return f(unpack(params, 1, params.n)) end
co = coroutine.create(newf)
local current = running()
if not current then
if err == id then
return oldpcall(f, ...)
else
if select("#", ...) > 0 then
local oldf, params = f, pack(...)
f = function() return oldf(unpack(params, 1, params.n)) end
end
return oldxpcall(f, err)
end
else
local res, co = oldpcall(coroutine.create, f)
if not res then
local params = pack(...)
local newf = function() return f(unpack(params, 1, params.n)) end
co = coroutine.create(newf)
end
coromap[co] = current
return performResume(err, co, ...)
end
coromap[co] = (running() or "mainthread")
return performResume(err, co, ...)
end

local function corunning(coro)
Expand All @@ -85,10 +102,6 @@ end
-- Implements pcall with coroutines
-------------------------------------------------------------------------------

local function id(trace, ...)
return ...
end

function copcall(f, ...)
return coxpcall(f, id, ...)
end
Expand Down

0 comments on commit 66f0ee6

Please sign in to comment.