summaryrefslogtreecommitdiff
path: root/xmake
diff options
context:
space:
mode:
authorruki <[email protected]>2025-08-28 22:45:48 +0800
committerruki <[email protected]>2025-08-28 11:35:54 +0800
commit8a331ab64fe560924b8bc3ab3dc4ac2831dd8920 (patch)
tree1b7406be4f6db49c198d36d180b4f98ff8185847 /xmake
parenta3ff692d028873e06cc9827e1ff72dc9ec8b54d4 (diff)
add thread semaphore
Diffstat (limited to 'xmake')
-rw-r--r--xmake/core/base/thread.lua116
-rw-r--r--xmake/core/sandbox/modules/import/core/base/thread.lua55
2 files changed, 159 insertions, 12 deletions
diff --git a/xmake/core/base/thread.lua b/xmake/core/base/thread.lua
index 5428dc3f2..c924724b8 100644
--- a/xmake/core/base/thread.lua
+++ b/xmake/core/base/thread.lua
@@ -19,10 +19,11 @@
--
-- define module
-local thread = thread or {}
-local _thread = _thread or {}
-local _mutex = _mutex or {}
-local _event = _event or {}
+local thread = thread or {}
+local _thread = _thread or {}
+local _mutex = _mutex or {}
+local _event = _event or {}
+local _semaphore = _semaphore or {}
-- load modules
local io = require("base/io")
@@ -104,6 +105,10 @@ function _thread:start()
elseif type(arg) == "table" and arg._EVENT and arg.cdata then
thread.event_incref(arg:cdata())
arg = {event = true, name = arg:name(), caddr = libc.dataptr(arg:cdata())}
+ -- is semaphore? we can only pass cdata address
+ elseif type(arg) == "table" and arg._SEMAPHORE and arg.cdata then
+ thread.semaphore_incref(arg:cdata())
+ arg = {semaphore = true, name = arg:name(), caddr = libc.dataptr(arg:cdata())}
end
table.insert(argv, arg)
end
@@ -379,8 +384,7 @@ function _event:close()
ok = thread.event_exit(self:cdata())
if ok then
- self._MUTEX = nil
- self._LOCKED_NUM = 0
+ self._EVENT = nil
end
return ok
end
@@ -401,8 +405,92 @@ end
-- gc(event)
function _event:__gc()
if self:cdata() and thread.event_exit(self:cdata()) then
- self._MUTEX = nil
- self._LOCKED_NUM = 0
+ self._EVENT = nil
+ end
+end
+
+-- new an semaphore
+function _semaphore.new(name, cdata)
+ local semaphore = table.inherit(_semaphore)
+ semaphore._NAME = name
+ semaphore._SEMAPHORE = cdata
+ setmetatable(semaphore, _semaphore)
+ return semaphore
+end
+
+-- get the semaphore name
+function _semaphore:name()
+ return self._NAME
+end
+
+-- get the cdata
+function _semaphore:cdata()
+ return self._SEMAPHORE
+end
+
+-- post semaphore
+--
+-- @param value the semaphore value
+--
+-- @return ok, errors
+--
+function _semaphore:post(value)
+ local ok, errors = self:_ensure_opened()
+ if not ok then
+ return false, errors
+ end
+
+ if not thread.semaphore_post(self:cdata(), value) then
+ return false, string.format("%s: post failed!", self)
+ end
+ return true
+end
+
+-- wait semaphore
+function _semaphore:wait(timeout)
+ local ok, errors = self:_ensure_opened()
+ if not ok then
+ return false, errors
+ end
+
+ local ok, errors = thread.semaphore_wait(self:cdata(), timeout)
+ if ok < 0 then
+ return false, string.format("%s: wait failed, errors: %s!", self, errors or "unknown")
+ end
+ return ok
+end
+
+-- close semaphore
+function _semaphore:close()
+ local ok, errors = self:_ensure_opened()
+ if not ok then
+ return false, errors
+ end
+
+ ok = thread.semaphore_exit(self:cdata())
+ if ok then
+ self._SEMAPHORE = nil
+ end
+ return ok
+end
+
+-- ensure the file is opened
+function _semaphore:_ensure_opened()
+ if not self:cdata() then
+ return false, string.format("%s: has been closed!", self)
+ end
+ return true
+end
+
+-- tostring(semaphore)
+function _semaphore:__tostring()
+ return "<semaphore: " .. (self:name() or tostring(self:cdata())) .. ">"
+end
+
+-- gc(semaphore)
+function _semaphore:__gc()
+ if self:cdata() and thread.semaphore_exit(self:cdata()) then
+ self._SEMAPHORE = nil
end
end
@@ -486,6 +574,8 @@ function thread._run_thread(callback_str, callinfo_str)
arg = _mutex.new(arg.name, libc.ptraddr(arg.caddr))
elseif type(arg) == "table" and arg.event and arg.caddr then
arg = _event.new(arg.name, libc.ptraddr(arg.caddr))
+ elseif type(arg) == "table" and arg.semaphore and arg.caddr then
+ arg = _semaphore.new(arg.name, libc.ptraddr(arg.caddr))
end
table.insert(newargv, arg)
end
@@ -516,6 +606,16 @@ function thread.event(name)
end
end
+-- open a semaphore
+function thread.semaphore(name, value)
+ local semaphore = thread.semaphore_init(value or 0)
+ if semaphore then
+ return _semaphore.new(name, semaphore)
+ else
+ return nil, string.format("cannot open semaphore: %s", os.strerror())
+ end
+end
+
-- return module
return thread
diff --git a/xmake/core/sandbox/modules/import/core/base/thread.lua b/xmake/core/sandbox/modules/import/core/base/thread.lua
index d3b5d4ae4..cb8de9ac6 100644
--- a/xmake/core/sandbox/modules/import/core/base/thread.lua
+++ b/xmake/core/sandbox/modules/import/core/base/thread.lua
@@ -25,10 +25,11 @@ local thread = require("base/thread")
local raise = require("sandbox/modules/raise")
-- define module
-local sandbox_core_base_thread = sandbox_core_base_thread or {}
-local sandbox_core_base_thread_instance = sandbox_core_base_thread_instance or {}
-local sandbox_core_base_thread_mutex = sandbox_core_base_thread_mutex or {}
-local sandbox_core_base_thread_event = sandbox_core_base_thread_event or {}
+local sandbox_core_base_thread = sandbox_core_base_thread or {}
+local sandbox_core_base_thread_instance = sandbox_core_base_thread_instance or {}
+local sandbox_core_base_thread_mutex = sandbox_core_base_thread_mutex or {}
+local sandbox_core_base_thread_event = sandbox_core_base_thread_event or {}
+local sandbox_core_base_thread_semaphore = sandbox_core_base_thread_semaphore or {}
-- export the thread status
sandbox_core_base_thread.STATUS_READY = thread.STATUS_READY
@@ -135,6 +136,31 @@ function sandbox_core_base_thread_event.close(event)
end
end
+-- post semaphore
+function sandbox_core_base_thread_semaphore.post(semaphore, value)
+ local ok, errors = semaphore:_post(value)
+ if not ok then
+ raise(errors)
+ end
+end
+
+-- wait semaphore
+function sandbox_core_base_thread_semaphore.wait(semaphore, timeout)
+ local ok, errors = semaphore:_wait(timeout)
+ if ok < 0 then
+ raise(errors)
+ end
+ return ok
+end
+
+-- close semaphore
+function sandbox_core_base_thread_semaphore.close(semaphore)
+ local ok, errors = semaphore:_close()
+ if not ok then
+ raise(errors)
+ end
+end
+
-- new thread
function sandbox_core_base_thread.new(callback, opt)
local instance, errors = thread.new(callback, opt)
@@ -210,6 +236,27 @@ function sandbox_core_base_thread.event(name)
return event
end
+-- open a semaphore
+function sandbox_core_base_thread.semaphore(name, value)
+ local semaphore, errors = thread.semaphore(name, value)
+ if not semaphore then
+ raise(errors)
+ end
+
+ -- hook filesemaphore interfaces
+ local hooked = {}
+ for name, func in pairs(sandbox_core_base_thread_semaphore) do
+ if not name:startswith("_") and type(func) == "function" then
+ hooked["_" .. name] = semaphore["_" .. name] or semaphore[name]
+ hooked[name] = func
+ end
+ end
+ for name, func in pairs(hooked) do
+ semaphore[name] = func
+ end
+ return semaphore
+end
+
-- return module
return sandbox_core_base_thread