1
0
Fork 0
mirror of https://gitlab.com/niansa/libcrosscoro.git synced 2025-03-06 20:53:32 +01:00
libcrosscoro/src/event.cpp
Josh Baldwin 303cc3384c
Issue 5/clang format (#6)
* clang-format all existing files

* Add detailed comments for event
2020-10-14 08:53:00 -06:00

55 lines
1.5 KiB
C++

#include "coro/event.hpp"
namespace coro
{
event::event(bool initially_set) noexcept : m_state((initially_set) ? static_cast<void*>(this) : nullptr)
{
}
auto event::set() noexcept -> void
{
// Exchange the state to this, if the state was previously not this, then traverse the list
// of awaiters and resume their coroutines.
void* old_value = m_state.exchange(this, std::memory_order::acq_rel);
if (old_value != this)
{
auto* waiters = static_cast<awaiter*>(old_value);
while (waiters != nullptr)
{
auto* next = waiters->m_next;
waiters->m_awaiting_coroutine.resume();
waiters = next;
}
}
}
auto event::awaiter::await_suspend(std::coroutine_handle<> awaiting_coroutine) noexcept -> bool
{
const void* const set_state = &m_event;
m_awaiting_coroutine = awaiting_coroutine;
// This value will update if other threads write to it via acquire.
void* old_value = m_event.m_state.load(std::memory_order::acquire);
do
{
// Resume immediately if already in the set state.
if (old_value == set_state)
{
return false;
}
m_next = static_cast<awaiter*>(old_value);
} while (!m_event.m_state.compare_exchange_weak(
old_value, this, std::memory_order::release, std::memory_order::acquire));
return true;
}
auto event::reset() noexcept -> void
{
void* old_value = this;
m_state.compare_exchange_strong(old_value, nullptr, std::memory_order::acquire);
}
} // namespace coro