dnsjit/include/dnsjit/core/thread.lua
Daniel Baumann 1ce56b1dca
Adding upstream version 1.2.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-09 08:33:20 +01:00

141 lines
4.2 KiB
Lua

-- Copyright (c) 2018-2022, OARC, Inc.
-- All rights reserved.
--
-- This file is part of dnsjit.
--
-- dnsjit is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- dnsjit is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
-- dnsjit.core.thread
-- POSIX thread with separate Lua state
-- local thr = require("dnsjit.core.thread").new()
-- thr:start(function(thr)
-- print("Hello from thread")
-- print("got:", thr:pop(), " = ", thr:pop(3))
-- end)
-- thr:push("value from main", 1, 2, 3)
-- thr:stop()
--
-- Start a new POSIX thread with it's own Lua state.
-- Sharable objects can be passed to the thread by pushing and poping them of
-- the thread stack.
-- The Thread object and any other objects passed to the thread needs to be
-- kept alive as long as the thread is running.
module(...,package.seeall)
require("dnsjit.core.thread_h")
local ffi = require("ffi")
local C = ffi.C
local t_name = "core_thread_t"
local core_thread_t
local Thread = {
_in_thread = function(thr, bytecode)
thr = ffi.cast("core_thread_t*", thr)
loadstring(bytecode)(thr)
end
}
-- Create a new Thread object.
function Thread.new()
local self = core_thread_t()
C.core_thread_init(self)
ffi.gc(self, C.core_thread_destroy)
return self
end
-- Return the Log object to control logging of this instance or module.
function Thread:log()
if self == nil then
return C.core_thread_log()
end
return self._log
end
-- Start the thread and execute the given function in a separate Lua state,
-- first argument to the function will be the Thread object that created it.
-- Returns 0 on success.
function Thread:start(func)
local bc = string.dump(func)
return C.core_thread_start(self, bc, #bc)
end
-- Wait for the thread to return.
-- Returns 0 on success.
function Thread:stop()
return C.core_thread_stop(self)
end
-- Push string(s), number(s) or sharable object(s) onto the thread stack so
-- they can be retrieved inside the thread using
-- .IR pop() .
-- The sharable object(s) needs to be kept alive as long as the thread is
-- running, strings and numbers are copied.
function Thread:push(...)
for _, obj in pairs({...}) do
local t = type(obj)
if t == "string" then
C.core_thread_push_string(self, obj, #obj)
elseif t == "number" then
C.core_thread_push_int64(self, obj)
else
local ptr, type, module = obj:share()
C.core_thread_push(self, ptr, type, #type, module, #module)
end
end
end
-- Pop value(s) off the thread stack, should only be called within the thread.
-- If
-- .I num
-- is not given then one value is poped.
-- Returns nil if no values are left on the stack.
function Thread:pop(num)
if num == nil or num == 1 then
local item = C.core_thread_pop(self)
if item == nil then
return
end
if item.ptr == nil then
if item.str == nil then
return tonumber(item.i64)
end
return ffi.string(item.str)
end
require(ffi.string(item.module))
return ffi.cast(ffi.string(item.type), item.ptr)
end
local ret = {}
for n = 1, num do
local item = C.core_thread_pop(self)
if item == nil then break end
if item.ptr == nil then
if item.str == nil then
table.insert(ret, tonumber(item.i64))
else
table.insert(ret, ffi.string(item.str))
end
else
require(ffi.string(item.module))
table.insert(ret, ffi.cast(ffi.string(item.type), item.ptr))
end
end
return unpack(ret)
end
core_thread_t = ffi.metatype(t_name, { __index = Thread })
-- dnsjit.core.channel (3)
return Thread