c-resources/CPlusPlus20ForProgrammers-m.../examples/libraries/concurrencpp/source/task.cpp

105 lines
2.7 KiB
C++

#include "concurrencpp/task.h"
#include "concurrencpp/results/impl/consumer_context.h"
#include <cstring>
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<coroutine_handle_functor>(m_vtable)) {
return callable_vtable<coroutine_handle_functor>::move_destroy(rhs.m_buffer, m_buffer);
}
if (contains<await_via_functor>(m_vtable)) {
return callable_vtable<await_via_functor>::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<void> 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<coroutine_handle_functor>(vtable)) {
return callable_vtable<coroutine_handle_functor>::execute_destroy(m_buffer);
}
if (contains<await_via_functor>(vtable)) {
return callable_vtable<await_via_functor>::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<coroutine_handle_functor>(vtable)) {
return callable_vtable<coroutine_handle_functor>::destroy(m_buffer);
}
if (contains<await_via_functor>(vtable)) {
return callable_vtable<await_via_functor>::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;
}