forstio/source/async.cpp

240 lines
4.7 KiB
C++
Raw Normal View History

#include "async.h"
#include <cassert>
namespace gin {
namespace {
2020-08-09 02:04:48 +02:00
thread_local EventLoop *local_loop = nullptr;
EventLoop &currentEventLoop() {
EventLoop *loop = local_loop;
assert(loop);
return *loop;
}
} // namespace
2020-08-20 00:36:21 +02:00
ConveyorNode::ConveyorNode() : child{nullptr} {}
2020-08-20 00:36:21 +02:00
ConveyorNode::ConveyorNode(Own<ConveyorNode> &&node) : child{std::move(node)} {}
2020-08-20 00:36:21 +02:00
void ConveyorStorage::setParent(ConveyorStorage *p) { parent = p; }
2020-08-20 00:36:21 +02:00
ConveyorBase::ConveyorBase(Own<ConveyorNode> &&node_p,
ConveyorStorage *storage_p)
: node{std::move(node_p)}, storage{storage_p} {}
2020-08-18 19:59:59 +02:00
PropagateError::Helper::Helper(Error &&error) : error{std::move(error)} {}
Error PropagateError::Helper::asError() { return std::move(error); }
PropagateError::Helper PropagateError::operator()(const Error &error) const {
Error err{error};
return PropagateError::Helper{std::move(err)};
}
PropagateError::Helper PropagateError::operator()(Error &&error) {
return PropagateError::Helper{std::move(error)};
}
2020-08-20 00:36:21 +02:00
Event::Event() : Event(currentEventLoop()) {}
2020-08-09 02:04:48 +02:00
Event::Event(EventLoop &loop) : loop{loop} {}
2020-08-09 02:03:09 +02:00
Event::~Event() { disarm(); }
2020-08-09 02:03:09 +02:00
void Event::armNext() {
assert(&loop == local_loop);
if (prev == nullptr) {
// Push the next_insert_point back by one
// and inserts itself before that
next = *loop.next_insert_point;
prev = loop.next_insert_point;
*prev = this;
if (next) {
next->prev = &next;
}
// Set the new insertion ptr location to next
loop.next_insert_point = &next;
// Pushes back the later insert point if it was pointing at the
// previous event
if (loop.later_insert_point == prev) {
loop.later_insert_point = &next;
}
// If tail points at the same location then
// we are at the end and have to update tail then.
// Technically should be possible by checking if
// next is a `nullptr`
if (loop.tail == prev) {
loop.tail = &next;
}
loop.setRunnable(true);
2020-08-09 02:04:48 +02:00
}
}
2020-08-09 02:03:09 +02:00
void Event::armLater() {
assert(&loop == local_loop);
if (prev == nullptr) {
next = *loop.later_insert_point;
prev = loop.later_insert_point;
*prev = this;
if (next) {
next->prev = &next;
}
loop.later_insert_point = &next;
if (loop.tail == prev) {
loop.tail = &next;
}
loop.setRunnable(true);
2020-08-09 02:04:48 +02:00
}
}
2020-08-09 02:03:09 +02:00
void Event::armLast() {
assert(&loop == local_loop);
2020-08-09 02:04:48 +02:00
if (prev == nullptr) {
next = *loop.later_insert_point;
prev = loop.later_insert_point;
*prev = this;
if (next) {
next->prev = &next;
}
2020-08-09 02:04:48 +02:00
if (loop.tail == prev) {
loop.tail = &next;
}
loop.setRunnable(true);
2020-08-09 02:04:48 +02:00
}
}
void Event::disarm() {
2020-08-20 00:36:21 +02:00
if (prev != nullptr) {
if (loop.tail == &next) {
loop.tail = prev;
}
if (loop.next_insert_point == &next) {
loop.next_insert_point = prev;
}
*prev = next;
if (next) {
next->prev = prev;
}
prev = nullptr;
next = nullptr;
2020-08-09 02:04:48 +02:00
}
}
2020-08-20 00:36:21 +02:00
bool Event::isArmed() const { return prev != nullptr; }
2020-08-09 02:03:09 +02:00
void EventLoop::setRunnable(bool runnable) { is_runnable = runnable; }
2020-08-09 02:03:09 +02:00
EventLoop::EventLoop() {}
2020-08-06 02:19:05 +02:00
2020-08-25 19:51:45 +02:00
EventLoop::EventLoop(Own<EventPort>&& event_port):
event_port{std::move(event_port)}
{}
2020-08-09 02:03:09 +02:00
EventLoop::~EventLoop() { assert(local_loop != this); }
2020-08-06 02:19:05 +02:00
2020-08-09 02:03:09 +02:00
void EventLoop::enterScope() {
assert(!local_loop);
local_loop = this;
2020-08-06 02:19:05 +02:00
}
2020-08-09 02:03:09 +02:00
void EventLoop::leaveScope() {
assert(local_loop == this);
local_loop = nullptr;
}
2020-08-20 00:52:51 +02:00
bool EventLoop::turn() {
Event *event = head;
2020-08-20 00:50:36 +02:00
2020-08-20 00:52:51 +02:00
if (!event) {
2020-08-20 00:50:36 +02:00
return false;
}
head = event->next;
2020-08-20 00:52:51 +02:00
if (head) {
2020-08-20 00:50:36 +02:00
head->prev = &head;
}
next_insert_point = &head;
2020-08-20 00:52:51 +02:00
if (later_insert_point == &event->next) {
2020-08-20 00:50:36 +02:00
later_insert_point = &head;
}
2020-08-20 00:52:51 +02:00
if (tail == &event->next) {
2020-08-20 00:50:36 +02:00
tail = &head;
}
event->next = nullptr;
event->prev = nullptr;
next_insert_point = &head;
2020-08-25 19:51:45 +02:00
event->fire();
2020-08-20 00:50:36 +02:00
return true;
}
2020-08-09 02:04:48 +02:00
bool EventLoop::wait(const std::chrono::steady_clock::duration &duration) {
return false;
}
2020-08-09 02:04:48 +02:00
bool EventLoop::wait(const std::chrono::steady_clock::time_point &time_point) {
return false;
}
2020-08-09 02:03:09 +02:00
bool EventLoop::wait() { return false; }
2020-08-06 02:19:05 +02:00
2020-08-20 00:50:36 +02:00
bool EventLoop::poll() {
2020-08-20 00:52:51 +02:00
while (head) {
if (!turn()) {
2020-08-20 00:50:36 +02:00
return false;
}
2020-08-20 00:52:51 +02:00
}
2020-08-20 00:50:36 +02:00
return true;
}
2020-08-09 02:03:09 +02:00
2020-08-25 19:51:45 +02:00
EventPort* EventLoop::eventPort(){
return event_port.get();
}
2020-08-09 02:04:48 +02:00
WaitScope::WaitScope(EventLoop &loop) : loop{loop} { loop.enterScope(); }
2020-08-09 02:03:09 +02:00
WaitScope::~WaitScope() { loop.leaveScope(); }
void WaitScope::wait() { loop.wait(); }
2020-08-09 02:04:48 +02:00
void WaitScope::wait(const std::chrono::steady_clock::duration &duration) {
loop.wait(duration);
}
2020-08-09 02:04:48 +02:00
void WaitScope::wait(const std::chrono::steady_clock::time_point &time_point) {
loop.wait(time_point);
}
2020-08-09 02:03:09 +02:00
void WaitScope::poll() { loop.poll(); }
2020-08-20 00:36:21 +02:00
ConvertConveyorNodeBase::ConvertConveyorNodeBase(Own<ConveyorNode> &&dep)
: ConveyorNode{std::move(dep)} {}
void ConvertConveyorNodeBase::getResult(ErrorOrValue &err_or_val) {
getImpl(err_or_val);
}
2020-08-23 15:47:14 +02:00
2020-08-24 12:47:18 +02:00
void AttachConveyorNodeBase::getResult(ErrorOrValue &err_or_val) {
if (child) {
2020-08-23 15:47:14 +02:00
child->getResult(err_or_val);
}
}
2020-08-09 02:04:48 +02:00
} // namespace gin