Skip to content

Commit 28a0ad9

Browse files
Remove unused Semaphore and fix pending_tasks publish ordering
Delete the unused Semaphore primitive and its test rather than fixing its multi-waiter wakeup bug, since it is dead code referenced only by its own test. Increment pending_tasks before publishing the task in Pool::submit and in the get_task re-enqueue path, so a worker can never dequeue a task before its count is registered (over-counting is safe; under-counting could transiently underflow). Reword the ~Scheduler comments to describe the real failure mode: a dangling current_pool leads to shared_from_this() on a destroyed pool (undefined behaviour), not a guaranteed bad_weak_ptr throw. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent fb14e22 commit 28a0ad9

5 files changed

Lines changed: 10 additions & 226 deletions

File tree

src/threading/scheduler/Pool.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ namespace threading {
142142
}
143143

144144
const std::size_t bucket = queue::priority_index(task.task->priority);
145-
buckets[bucket]->enqueue(std::move(task));
146145
pending_tasks.fetch_add(1, std::memory_order_release);
146+
buckets[bucket]->enqueue(std::move(task));
147147

148148
const std::lock_guard<std::mutex> lock(mutex);
149149
if (clear_idle) {
@@ -294,8 +294,8 @@ namespace threading {
294294
// The task was dequeued but its lock isn't acquirable. Re-enqueue and
295295
// wait for someone to notify us when the lock state changes.
296296
const std::size_t bucket = queue::priority_index(task.task->priority);
297-
buckets[bucket]->enqueue(std::move(task));
298297
pending_tasks.fetch_add(1, std::memory_order_release);
298+
buckets[bucket]->enqueue(std::move(task));
299299
}
300300
}
301301
live = false;

src/threading/scheduler/Scheduler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ namespace threading {
5050

5151
Scheduler::~Scheduler() {
5252
// The constructor installed a non-owning pointer to the main thread pool in this thread's
53-
// Pool::current_pool. Our pools are about to be destroyed, so leave no dangling pointer behind
54-
// for any later Pool::current() call on this thread (it would otherwise throw bad_weak_ptr from
55-
// the expired pool). Only clear it if it still refers to one of our pools, so we never disturb
56-
// an unrelated Scheduler that may share this thread.
53+
// Pool::current_pool. Our pools are about to be destroyed, so leave no dangling pointer behind for
54+
// any later Pool::current() call on this thread (shared_from_this() on a destroyed pool is undefined
55+
// behaviour, in practice observed as a bad_weak_ptr or a crash). Only clear it if it still refers to
56+
// one of our pools, so we never disturb an unrelated Scheduler that may share this thread.
5757
const std::lock_guard<std::mutex> lock(pools_mutex);
5858
for (const auto& pool : pools) {
5959
if (Pool::current_pool == pool.second.get()) {

src/threading/scheduler/Scheduler.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ namespace threading {
5353
*
5454
* The constructor points the creating thread's Pool::current_pool at the main thread pool so
5555
* work done before startup is attributed correctly. That pointer is non-owning, so once this
56-
* Scheduler (and therefore its pools) is destroyed it would dangle; any later ReactionTask
57-
* built on the same thread calls Pool::current() and would trip a bad_weak_ptr. Resetting it
58-
* here keeps the pointer's lifetime bounded by the Scheduler that set it.
56+
* Scheduler (and therefore its pools) is destroyed it would dangle; a later Pool::current()
57+
* would call shared_from_this() on a destroyed pool, which is undefined behaviour (in practice
58+
* observed as a bad_weak_ptr or a crash). Resetting it here keeps the pointer's lifetime bounded
59+
* by the Scheduler that set it.
5960
*/
6061
~Scheduler();
6162

src/threading/scheduler/queue/Semaphore.hpp

Lines changed: 0 additions & 93 deletions
This file was deleted.

tests/tests/threading/Semaphore.cpp

Lines changed: 0 additions & 124 deletions
This file was deleted.

0 commit comments

Comments
 (0)