2020-08-04 01:19:35 +02:00
|
|
|
#include "async.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
namespace gin {
|
|
|
|
namespace {
|
2020-08-09 02:04:48 +02:00
|
|
|
thread_local EventLoop *local_loop = nullptr;
|
2020-08-16 20:08:11 +02:00
|
|
|
|
|
|
|
EventLoop ¤tEventLoop() {
|
|
|
|
EventLoop *loop = local_loop;
|
|
|
|
assert(loop);
|
|
|
|
return *loop;
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
2020-08-20 00:36:21 +02:00
|
|
|
ConveyorNode::ConveyorNode() : child{nullptr} {}
|
2020-08-16 20:08:11 +02:00
|
|
|
|
2020-08-20 00:36:21 +02:00
|
|
|
ConveyorNode::ConveyorNode(Own<ConveyorNode> &&node) : child{std::move(node)} {}
|
2020-08-16 20:08:11 +02:00
|
|
|
|
2020-08-20 00:36:21 +02:00
|
|
|
void ConveyorStorage::setParent(ConveyorStorage *p) { parent = p; }
|
2020-08-16 20:08:11 +02:00
|
|
|
|
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
|
|
|
|
2020-08-16 20:08:11 +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-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
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-04 01:19:35 +02:00
|
|
|
|
2020-08-09 02:03:09 +02:00
|
|
|
Event::~Event() { disarm(); }
|
2020-08-04 01:19:35 +02:00
|
|
|
|
2020-08-09 02:03:09 +02:00
|
|
|
void Event::armNext() {
|
2020-08-09 02:09:49 +02:00
|
|
|
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-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
2020-08-09 02:03:09 +02:00
|
|
|
void Event::armLater() {
|
2020-08-09 02:09:49 +02:00
|
|
|
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-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
2020-08-09 02:03:09 +02:00
|
|
|
void Event::armLast() {
|
2020-08-09 02:09:49 +02:00
|
|
|
assert(&loop == local_loop);
|
2020-08-09 02:04:48 +02:00
|
|
|
|
2020-08-09 02:09:49 +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
|
|
|
|
2020-08-09 02:09:49 +02:00
|
|
|
if (loop.tail == prev) {
|
|
|
|
loop.tail = &next;
|
|
|
|
}
|
2020-08-04 01:19:35 +02:00
|
|
|
|
2020-08-09 02:09:49 +02:00
|
|
|
loop.setRunnable(true);
|
2020-08-09 02:04:48 +02:00
|
|
|
}
|
2020-08-09 02:09:49 +02:00
|
|
|
}
|
2020-08-04 01:19:35 +02:00
|
|
|
|
2020-08-09 02:09:49 +02:00
|
|
|
void Event::disarm() {
|
2020-08-20 00:36:21 +02:00
|
|
|
if (prev != nullptr) {
|
2020-08-09 02:09:49 +02:00
|
|
|
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-04 01:19:35 +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-04 01:19:35 +02:00
|
|
|
|
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() {
|
2020-08-09 02:09:49 +02:00
|
|
|
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() {
|
2020-08-09 02:09:49 +02:00
|
|
|
assert(local_loop == this);
|
|
|
|
local_loop = nullptr;
|
2020-08-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
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) {
|
2020-08-09 02:09:49 +02:00
|
|
|
return false;
|
2020-08-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
2020-08-09 02:04:48 +02:00
|
|
|
bool EventLoop::wait(const std::chrono::steady_clock::time_point &time_point) {
|
2020-08-09 02:09:49 +02:00
|
|
|
return false;
|
2020-08-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
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-04 01:19:35 +02:00
|
|
|
|
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) {
|
2020-08-09 02:09:49 +02:00
|
|
|
loop.wait(duration);
|
2020-08-04 01:19:35 +02:00
|
|
|
}
|
|
|
|
|
2020-08-09 02:04:48 +02:00
|
|
|
void WaitScope::wait(const std::chrono::steady_clock::time_point &time_point) {
|
2020-08-09 02:09:49 +02:00
|
|
|
loop.wait(time_point);
|
2020-08-04 01:19:35 +02:00
|
|
|
}
|
2020-08-09 02:03:09 +02:00
|
|
|
|
|
|
|
void WaitScope::poll() { loop.poll(); }
|
2020-08-16 20:08:11 +02:00
|
|
|
|
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
|