#include "concurrencpp/task.h" #include "concurrencpp/results/impl/consumer_context.h" #include using concurrencpp::task; using concurrencpp::details::vtable; static_assert(sizeof(task) == concurrencpp::details::task_constants::total_size, "concurrencpp::task - object size is bigger than a cache-line."); using concurrencpp::details::callable_vtable; using concurrencpp::details::await_via_functor; using concurrencpp::details::coroutine_handle_functor; void task::build(task&& rhs) noexcept { m_vtable = std::exchange(rhs.m_vtable, nullptr); if (m_vtable == nullptr) { return; } if (contains(m_vtable)) { return callable_vtable::move_destroy(rhs.m_buffer, m_buffer); } if (contains(m_vtable)) { return callable_vtable::move_destroy(rhs.m_buffer, m_buffer); } const auto move_destroy_fn = m_vtable->move_destroy_fn; if (vtable::trivially_copiable_destructible(move_destroy_fn)) { std::memcpy(m_buffer, rhs.m_buffer, details::task_constants::buffer_size); return; } move_destroy_fn(rhs.m_buffer, m_buffer); } void task::build(details::coroutine_handle coro_handle) noexcept { build(details::coroutine_handle_functor {coro_handle}); } task::task() noexcept : m_buffer(), m_vtable(nullptr) {} task::task(task&& rhs) noexcept { build(std::move(rhs)); } task::~task() noexcept { clear(); } void task::operator()() { const auto vtable = std::exchange(m_vtable, nullptr); if (vtable == nullptr) { return; } if (contains(vtable)) { return callable_vtable::execute_destroy(m_buffer); } if (contains(vtable)) { return callable_vtable::execute_destroy(m_buffer); } vtable->execute_destroy_fn(m_buffer); } task& task::operator=(task&& rhs) noexcept { if (this == &rhs) { return *this; } clear(); build(std::move(rhs)); return *this; } void task::clear() noexcept { if (m_vtable == nullptr) { return; } const auto vtable = std::exchange(m_vtable, nullptr); if (contains(vtable)) { return callable_vtable::destroy(m_buffer); } if (contains(vtable)) { return callable_vtable::destroy(m_buffer); } auto destroy_fn = vtable->destroy_fn; if (vtable::trivially_destructable(destroy_fn)) { return; } destroy_fn(m_buffer); } task::operator bool() const noexcept { return m_vtable != nullptr; }