diff options
| author | ruki <[email protected]> | 2025-10-05 23:46:57 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-10-05 23:46:57 +0800 |
| commit | be7b09dff7df31221ee205e1a8c086e9ee3a5568 (patch) | |
| tree | 7cc111cbed301fde4ece97d3e1efabdc9671bcb7 | |
| parent | 21dbefdf512d2b0a7d85fb768d3484d3c19b1d51 (diff) | |
fix semaphore
| -rw-r--r-- | xmake/core/base/scheduler.lua | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index 5eaa60415..a3dce684b 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -31,6 +31,7 @@ local string = require("base/string") local poller = require("base/poller") local timer = require("base/timer") local hashset = require("base/hashset") +local queue = require("base/queue") local coroutine = require("base/coroutine") local bit = require("base/bit") @@ -39,7 +40,8 @@ function _semaphore.new(name, value) local instance = table.inherit(_semaphore) instance._NAME = name instance._VALUE = value or 0 - instance._WAITING = hashset.new() + instance._WAITING = queue.new() + instance._POSTING = false setmetatable(instance, _semaphore) return instance end @@ -51,22 +53,25 @@ end -- post the semaphore value function _semaphore:post(value) + if self._POSTING then + return self._VALUE + end + self._POSTING = true local new_value = self._VALUE + value self._VALUE = new_value if new_value > 0 then - local pending = {} local waiting = self._WAITING - for item in waiting:items() do - if #pending < new_value then - table.insert(pending, item) - else + local post_count = 0 + while not waiting:empty() do + local item = waiting:pop() + scheduler:co_resume(item) + post_count = post_count + 1 + if post_count >= new_value then break end end - for _, item in ipairs(pending) do - scheduler:co_resume(item) - end end + self._POSTING = false return new_value end @@ -97,7 +102,7 @@ function _semaphore:wait(timeout) end -- wait semaphore - self._WAITING:insert(running) + self._WAITING:push(running) if timeout > 0 then scheduler:_timer():post(function (cancel) if running:is_suspended() then @@ -113,15 +118,16 @@ function _semaphore:wait(timeout) local value = self._VALUE if value > 0 then self._VALUE = value - 1 - self._WAITING:remove(running) return value end if timeout then break end + + -- continue to wait it + self._WAITING:push(running) end - self._WAITING:remove(running) return 0 end |
