diff --git a/src/rpp/rpp/schedulers/new_thread.hpp b/src/rpp/rpp/schedulers/new_thread.hpp index 30253a4bd..3c8a5f5a4 100644 --- a/src/rpp/rpp/schedulers/new_thread.hpp +++ b/src/rpp/rpp/schedulers/new_thread.hpp @@ -89,8 +89,10 @@ namespace rpp::schedulers { // Sleep until the current top is due, and wake as soon as the top changes // (an earlier schedulable was queued), so the loop recomputes the wait. - const auto* const top = state->queue.top().get(); - state->cv.wait_until(lock, top->get_timepoint(), [&] { return state->queue.is_empty() || state->queue.top().get() != top || state->queue.top()->is_disposed() || worker_strategy::now() >= state->queue.top()->get_timepoint(); }); + // The copy keeps the waited-for top alive, so its address cannot be reused + // by a newly queued schedulable while we wait. + const auto top = state->queue.top(); + state->cv.wait_until(lock, top->get_timepoint(), [&] { return state->queue.is_empty() || state->queue.top().get() != top.get() || state->queue.top()->is_disposed() || worker_strategy::now() >= state->queue.top()->get_timepoint(); }); continue; } } diff --git a/src/rpp/rpp/schedulers/run_loop.hpp b/src/rpp/rpp/schedulers/run_loop.hpp index 602020ad5..8af67a20e 100644 --- a/src/rpp/rpp/schedulers/run_loop.hpp +++ b/src/rpp/rpp/schedulers/run_loop.hpp @@ -68,8 +68,10 @@ namespace rpp::schedulers // Sleep until the current top is due, and wake as soon as the top changes // (an earlier schedulable was queued), so the loop recomputes the wait. - const auto* const top = m_queue.top().get(); - m_cv.wait_until(lock, top->get_timepoint(), [&]() { return is_disposed() || m_queue.is_empty() || m_queue.top().get() != top || m_queue.top()->is_disposed() || m_queue.top()->get_timepoint() <= worker_strategy::now(); }); + // The copy keeps the waited-for top alive, so its address cannot be reused + // by a newly queued schedulable while we wait. + const auto top = m_queue.top(); + m_cv.wait_until(lock, top->get_timepoint(), [&]() { return is_disposed() || m_queue.is_empty() || m_queue.top().get() != top.get() || m_queue.top()->is_disposed() || m_queue.top()->get_timepoint() <= worker_strategy::now(); }); } return {}; }