creation of sink before loop is set as current

This commit is contained in:
keldu.magnus 2020-08-26 15:30:48 +02:00
parent c9013a159f
commit 33d24c31d6
2 changed files with 85 additions and 12 deletions

View File

@ -1,6 +1,9 @@
#include "async.h" #include "async.h"
#include <cassert> #include <cassert>
#include <algorithm>
#include <iostream>
namespace gin { namespace gin {
namespace { namespace {
@ -134,10 +137,10 @@ bool Event::isArmed() const { return prev != nullptr; }
void EventLoop::setRunnable(bool runnable) { is_runnable = runnable; } void EventLoop::setRunnable(bool runnable) { is_runnable = runnable; }
EventLoop::EventLoop() {} EventLoop::EventLoop() : daemons{*this} {}
EventLoop::EventLoop(Own<EventPort>&& event_port): EventLoop::EventLoop(Own<EventPort>&& event_port):
event_port{std::move(event_port)} event_port{std::move(event_port)}, daemons{*this}
{} {}
EventLoop::~EventLoop() { assert(local_loop != this); } EventLoop::~EventLoop() { assert(local_loop != this); }
@ -221,6 +224,22 @@ void WaitScope::wait(const std::chrono::steady_clock::time_point &time_point) {
void WaitScope::poll() { loop.poll(); } void WaitScope::poll() { loop.poll(); }
ConveyorSink::ConveyorSink(EventLoop& loop):
Event(loop)
{}
void ConveyorSink::destroySinkConveyorNode(ConveyorNode& node){
if(!isArmed()){
armLast();
}
while(!delete_nodes.empty()){
auto result = std::find_if(sink_nodes.begin(), sink_nodes.end(), [&node](Own<ConveyorNode>& element){
return &node == element.get();
});
}
}
ConvertConveyorNodeBase::ConvertConveyorNodeBase(Own<ConveyorNode> &&dep) ConvertConveyorNodeBase::ConvertConveyorNodeBase(Own<ConveyorNode> &&dep)
: ConveyorNode{std::move(dep)} {} : ConveyorNode{std::move(dep)} {}

View File

@ -171,9 +171,25 @@ public:
virtual Conveyor<void> onSignal(Signal signal) = 0; virtual Conveyor<void> onSignal(Signal signal) = 0;
}; };
class ConveyorSink { class SinkConveyorNodeBase;
class ConveyorSink : public Event {
private: private:
friend class SinkConveyorNodeBase;
void destroySinkConveyorNode(ConveyorNode& sink_node);
std::list<Own<ConveyorNode>> sink_nodes;
std::queue<ConveyorNode*> delete_nodes;
public: public:
ConveyorSink() = default;
ConveyorSink(EventLoop& loop);
void add(Conveyor<void>&& node);
void fire() override {
/// @todo delete dangling nodes
}
}; };
class EventLoop { class EventLoop {
@ -376,6 +392,15 @@ public:
: QueueBufferConveyorNodeBase(std::move(dep)), max_store{max_size} {} : QueueBufferConveyorNodeBase(std::move(dep)), max_store{max_size} {}
// Event // Event
void fire() override { void fire() override {
if(child){
if(!storage.empty()){
if(storage.front().isError()){
if(storage.front().error().isCritical()){
child = nullptr;
}
}
}
}
if (parent) { if (parent) {
parent->childFired(); parent->childFired();
if (!storage.empty()) { if (!storage.empty()) {
@ -464,19 +489,25 @@ public:
} }
}; };
template<typename ErrorFunc> class SinkConveyorNodeBase : public ConveyorNode, public ConveyorStorage, public Event {
class SinkConveyorNode : public ConveyorNode, public ConveyorStorage, public Event {
private: private:
ErrorFunc error_func; ConveyorSink* conveyor_sink;
public: public:
SinkConveyorNode(Own<ConveyorNode>&& node, ErrorFunc&& err_func): SinkConveyorNodeBase(Own<ConveyorNode>&& node, ConveyorSink& conv_sink):
ConveyorNode(std::move(node)), ConveyorNode(std::move(node)),
error_func{std::move(err_func)} conveyor_sink{&conv_sink}
{} {}
// Event // Event
void fire() override { void fire() override {
// Does nothing, because this acts as a sink // Queued for destruction of children, because this acts as a sink and no other event should
// be here
child = nullptr;
if(conveyor_sink){
conveyor_sink->destroySinkConveyorNode(*this);
conveyor_sink = nullptr;
}
} }
// ConveyorStorage // ConveyorStorage
@ -487,18 +518,41 @@ public:
return 0; return 0;
} }
// ConveyorNode
void getResult(ErrorOrValue &err_or_val) override {
err_or_val.as<Void>() = criticalError("In a sink node no result can be returned");
}
};
template<typename ErrorFunc>
class SinkConveyorNode : public SinkConveyorNodeBase {
private:
ErrorFunc error_func;
friend class ConveyorSink;
ConveyorSink* conveyor_sink;
public:
SinkConveyorNode(Own<ConveyorNode>&& node, ConveyorSink& conv_sink, ErrorFunc&& err_func):
SinkConveyorNodeBase(std::move(node), conv_sink),
error_func{std::move(err_func)}
{}
// ConveyorStorage
void childFired() override { void childFired() override {
if(child){ if(child){
ErrorOr<Void> dep_eov; ErrorOr<Void> dep_eov;
child->getResult(dep_eov); child->getResult(dep_eov);
if(dep_eov.isError()){ if(dep_eov.isError()){
if(dep_eov.error().isCritical()){
if(!isArmed()){
armLast();
}
}
error_func(dep_eov.error()); error_func(dep_eov.error());
} }
} }
} }
// ConveyorNode
void getResult(ErrorOrValue &err_or_val) override;
}; };
} // namespace gin } // namespace gin