summaryrefslogtreecommitdiff
path: root/server/src/async/async.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-01-22 15:18:27 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-01-22 15:18:27 +0800
commit4ffc826d7ce5ca57c2929e040ed5eefb53f9d115 (patch)
tree9087cb647ac573848cd44f6660cb7a460ea38e60 /server/src/async/async.lua
parentce28b76cfc597e0cef3a62d8f7e181cf7ff4c904 (diff)
downloadlua-language-server-4ffc826d7ce5ca57c2929e040ed5eefb53f9d115.zip
整理代码
Diffstat (limited to 'server/src/async/async.lua')
-rw-r--r--server/src/async/async.lua89
1 files changed, 89 insertions, 0 deletions
diff --git a/server/src/async/async.lua b/server/src/async/async.lua
new file mode 100644
index 00000000..8c75540c
--- /dev/null
+++ b/server/src/async/async.lua
@@ -0,0 +1,89 @@
+local thread = require 'bee.thread'
+local errlog = thread.channel 'errlog'
+local taskId = 0
+local idlePool = {}
+local runningList = {}
+
+local function createTask()
+ taskId = taskId + 1
+ local id = taskId
+ local requestName = 'request' .. tostring(id)
+ local responseName = 'response' .. tostring(id)
+ thread.newchannel(requestName)
+ thread.newchannel(responseName)
+ local buf = ([[
+package.cpath = %q
+package.path = %q
+local thread = require 'bee.thread'
+local request = thread.channel(%q)
+local response = thread.channel(%q)
+local errlog = thread.channel 'errlog'
+
+local function task()
+ local dump, env = request:bpop()
+ if env then
+ setmetatable(env, { __index = _ENV })
+ else
+ env = _ENV
+ end
+ local f, err = load(dump, '=task', 't', env)
+ if not f then
+ errlog:push(err)
+ return
+ end
+ local results = table.pack(pcall(f))
+ local ok = table.remove(results, 1)
+ if not ok then
+ local err = table.remove(results, 1)
+ errlog:push(err)
+ return
+ end
+ results.n = results.n - 1
+ response:push(results)
+end
+
+while true do
+ task()
+end
+]]):format(package.cpath, package.path, requestName, responseName)
+ log.debug('Create thread, id: ', id)
+ return {
+ id = id,
+ thread = thread.thread(buf),
+ request = thread.channel(requestName),
+ response = thread.channel(responseName),
+ }
+end
+
+local function call(dump, env, callback)
+ local task = table.remove(idlePool)
+ if not task then
+ task = createTask()
+ end
+ runningList[task.id] = {
+ task = task,
+ callback = callback,
+ }
+ task.request:push(dump, env)
+end
+
+local function onTick()
+ local ok, msg = errlog:pop()
+ if ok then
+ log.error(msg)
+ end
+ for id, running in pairs(runningList) do
+ local ok, results = running.task.response:pop()
+ if ok then
+ runningList[id] = nil
+ idlePool[#idlePool+1] = running.task
+ xpcall(running.callback, log.debug, table.unpack(results))
+ end
+ end
+end
+
+return {
+ onTick = onTick,
+ call = call,
+ require = require,
+}