Skip to content

Commit 51f3c0a

Browse files
committed
runtime: Add CallbackResult return value to all action operator()
BREAKING CHANGE: If you have implemented any Actions yourself, you will need to make sure the `operator()(const Sync& ...)` returns `cloe::CallbackResult`. You can use `CallbackResult::Ok` to achieve the same behavior.
1 parent 30b05f5 commit 51f3c0a

File tree

13 files changed

+182
-140
lines changed

13 files changed

+182
-140
lines changed

engine/src/coordinator.cpp

+35-23
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class TriggerRegistrar : public cloe::TriggerRegistrar {
6262
return manager_.make_trigger(source_, c);
6363
}
6464

65+
// TODO: Should these queue_trigger becomes inserts? Because if they are coming from
66+
// C++ then they should be from a single thread.
6567
void insert_trigger(const Conf& c) override { manager_.queue_trigger(source_, c); }
6668
void insert_trigger(TriggerPtr&& t) override { manager_.queue_trigger(std::move(t)); }
6769

@@ -168,44 +170,54 @@ void Coordinator::register_event(const std::string& key, EventFactoryPtr&& ef,
168170
std::bind(&Coordinator::execute_trigger, this, std::placeholders::_1, std::placeholders::_2));
169171
}
170172

171-
void Coordinator::execute_trigger(TriggerPtr&& t, const Sync& sync) {
173+
cloe::CallbackResult Coordinator::execute_trigger(TriggerPtr&& t, const Sync& sync) {
172174
logger()->debug("Execute trigger {}", inline_json(*t));
173-
(t->action())(sync, *executer_registrar_);
175+
auto result = (t->action())(sync, *executer_registrar_);
174176
if (!t->is_conceal()) {
175-
history_.emplace_back(HistoryTrigger{sync.time(), std::move(t)});
177+
history_.emplace_back(sync.time(), std::move(t));
176178
}
179+
return result;
177180
}
178181

179-
Duration Coordinator::process(const Sync& sync) {
182+
size_t Coordinator::process_pending_web_triggers(const Sync& sync) {
180183
// The only thing we need to do here is distribute the triggers from the
181184
// input queue into their respective storage locations. We are responsible
182185
// for thread safety here!
183-
auto now = sync.time();
186+
size_t count = 0;
184187
std::unique_lock guard(input_mutex_);
185188
while (!input_queue_.empty()) {
186-
auto tp = std::move(input_queue_.front());
189+
store_trigger(std::move(input_queue_.front()), sync);
187190
input_queue_.pop_front();
188-
tp->set_since(now);
191+
count++;
192+
}
193+
return count;
194+
}
189195

190-
// Decide where to put the trigger
191-
auto key = tp->event().name();
192-
if (storage_.count(key) == 0) {
193-
// This is a programming error, since we should not be able to come this
194-
// far at all.
195-
throw std::logic_error("cannot insert trigger with unregistered event");
196-
}
197-
try {
198-
logger()->debug("Insert trigger {}", inline_json(*tp));
199-
storage_[key]->emplace(std::move(tp), sync);
200-
} catch (TriggerError& e) {
201-
logger()->error("Error inserting trigger: {}", e.what());
202-
if (!allow_errors_) {
203-
throw;
204-
}
196+
void Coordinator::store_trigger(TriggerPtr&& tp, const Sync& sync) {
197+
tp->set_since(sync.time());
198+
199+
// Decide where to put the trigger
200+
auto key = tp->event().name();
201+
if (storage_.count(key) == 0) {
202+
// This is a programming error, since we should not be able to come this
203+
// far at all.
204+
throw std::logic_error("cannot insert trigger with unregistered event");
205+
}
206+
try {
207+
logger()->debug("Insert trigger {}", inline_json(*tp));
208+
storage_[key]->emplace(std::move(tp), sync);
209+
} catch (TriggerError& e) {
210+
logger()->error("Error inserting trigger: {}", e.what());
211+
if (!allow_errors_) {
212+
throw;
205213
}
206214
}
215+
}
207216

208-
return now;
217+
Duration Coordinator::process(const Sync& sync) {
218+
auto now = sync.time();
219+
process_pending_web_triggers(sync);
220+
return sync.time();
209221
}
210222

211223
namespace {

engine/src/coordinator.hpp

+14-16
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,21 @@
2222

2323
#pragma once
2424

25-
#include <list> // for list<>
26-
#include <map> // for map<>
27-
#include <memory> // for unique_ptr<>, shared_ptr<>
28-
#include <mutex> // for mutex
29-
#include <queue> // for queue<>
30-
#include <string> // for string
31-
#include <vector> // for vector<>
25+
#include <list> // for list<>
26+
#include <map> // for map<>
27+
#include <memory> // for unique_ptr<>, shared_ptr<>
28+
#include <mutex> // for mutex
29+
#include <queue> // for queue<>
30+
#include <string> // for string
31+
#include <vector> // for vector<>
3232

33-
#include <cloe/trigger.hpp> // for Trigger, Action, Event, ...
34-
35-
// Forward declaration:
36-
namespace cloe {
37-
class Registrar;
38-
}
33+
#include <cloe/cloe_fwd.hpp> // for Registrar
34+
#include <cloe/trigger.hpp> // for Trigger, Action, Event, ...
3935

4036
namespace engine {
4137

4238
// Forward declarations:
43-
class TriggerRegistrar; // from trigger_manager.cpp
39+
class TriggerRegistrar; // from coordinator.cpp
4440

4541
/**
4642
* TriggerUnknownAction is thrown when an Action cannot be created because the
@@ -120,13 +116,15 @@ class Coordinator {
120116
*/
121117
cloe::Duration process(const cloe::Sync&);
122118

119+
size_t process_pending_web_triggers(const cloe::Sync& sync);
123120
protected:
124121
cloe::ActionPtr make_action(const cloe::Conf& c) const;
125122
cloe::EventPtr make_event(const cloe::Conf& c) const;
126123
cloe::TriggerPtr make_trigger(cloe::Source s, const cloe::Conf& c) const;
127124
void queue_trigger(cloe::Source s, const cloe::Conf& c) { queue_trigger(make_trigger(s, c)); }
128-
void queue_trigger(cloe::TriggerPtr&& t);
129-
void execute_trigger(cloe::TriggerPtr&& t, const cloe::Sync& s);
125+
void queue_trigger(cloe::TriggerPtr&& tp);
126+
void store_trigger(cloe::TriggerPtr&& tp, const cloe::Sync& sync);
127+
cloe::CallbackResult execute_trigger(cloe::TriggerPtr&& tp, const cloe::Sync& sync);
130128

131129
// for access to protected methods
132130
friend TriggerRegistrar;

engine/src/utility/command.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void CommandExecuter::wait_all() {
128128

129129
namespace actions {
130130

131-
void Command::operator()(const cloe::Sync&, cloe::TriggerRegistrar&) { executer_->run(command_); }
131+
cloe::CallbackResult Command::operator()(const cloe::Sync&, cloe::TriggerRegistrar&) { executer_->run(command_); return cloe::CallbackResult::Ok; }
132132

133133
void Command::to_json(cloe::Json& j) const { command_.to_json(j); }
134134

engine/src/utility/command.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class Command : public cloe::Action {
8686
return std::make_unique<Command>(name(), command_, executer_);
8787
}
8888

89-
void operator()(const cloe::Sync&, cloe::TriggerRegistrar&) override;
89+
cloe::CallbackResult operator()(const cloe::Sync&, cloe::TriggerRegistrar&) override;
9090

9191
protected:
9292
void to_json(cloe::Json& j) const override;

optional/vtd/src/scp_action.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ class ScpAction : public cloe::Action {
3535
ScpAction(const std::string& name, std::shared_ptr<ScpTransceiver> scp_client, const std::string& msg)
3636
: cloe::Action(name), client_(scp_client), xml_(msg) {}
3737
cloe::ActionPtr clone() const override { return std::make_unique<ScpAction>(name(), client_, xml_); }
38-
void operator()(const cloe::Sync&, cloe::TriggerRegistrar&) override {
38+
cloe::CallbackResult operator()(const cloe::Sync&, cloe::TriggerRegistrar&) override {
3939
logger()->info("Sending SCP message: {}", xml_);
4040
client_->send(xml_);
41+
return cloe::CallbackResult::Ok;
4142
}
4243
bool is_significant() const override { return false; }
4344

plugins/basic/src/hmi_contact.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class UseContact : public Action {
207207
UseContact(const std::string& name, ContactMap<D>* m, const Conf& data)
208208
: Action(name), hmi_(m), data_(data) {}
209209
ActionPtr clone() const override { return std::make_unique<UseContact<D>>(name(), hmi_, data_); }
210-
void operator()(const Sync&, TriggerRegistrar&) override { from_json(*data_, *hmi_); }
210+
CallbackResult operator()(const Sync&, TriggerRegistrar&) override { from_json(*data_, *hmi_); return CallbackResult::Ok; }
211211

212212
protected:
213213
void to_json(Json& j) const override { j = *data_; }

runtime/include/cloe/conf/action.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ class Configure : public Action {
3939
conf_.erase("name");
4040
}
4141
ActionPtr clone() const override { return std::make_unique<Configure>(name(), ptr_, conf_); }
42-
void operator()(const Sync&, TriggerRegistrar&) override { ptr_->from_conf(conf_); }
42+
CallbackResult operator()(const Sync&, TriggerRegistrar&) override {
43+
ptr_->from_conf(conf_);
44+
return CallbackResult::Ok;
45+
}
4346

4447
protected:
4548
void to_json(Json& j) const override { j = *conf_; }

runtime/include/cloe/registrar.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ class DirectCallback : public Callback {
5555
auto& condition = dynamic_cast<E&>((*it)->event());
5656
if (condition(sync, args...)) {
5757
if ((*it)->is_sticky()) {
58-
this->execute((*it)->clone(), sync);
58+
auto result = this->execute((*it)->clone(), sync);
59+
if (result == CallbackResult::Unpin) {
60+
it = triggers_.erase(it);
61+
}
5962
} else {
6063
// Remove from trigger list and advance.
6164
this->execute(std::move(*it), sync);

runtime/include/cloe/trigger.hpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,18 @@ class Event : public Entity {
507507
using EventFactory = TriggerFactory<Event>;
508508
using EventFactoryPtr = std::unique_ptr<EventFactory>;
509509

510+
enum class CallbackResult {
511+
/// Default, use standard behavior.
512+
Ok,
513+
514+
/// Remove from callback if it was sticky.
515+
Unpin,
516+
};
517+
510518
/**
511519
* Interface the trigger manager must provide for executing triggers.
512520
*/
513-
using CallbackExecuter = std::function<void(TriggerPtr&&, const Sync&)>;
521+
using CallbackExecuter = std::function<CallbackResult(TriggerPtr&&, const Sync&)>;
514522

515523
/**
516524
* Callback provides the interface with which the global trigger manager,
@@ -555,7 +563,7 @@ class Callback {
555563
* Execute a trigger in the given sync context by passing it to the
556564
* executer.
557565
*/
558-
void execute(TriggerPtr&& t, const Sync& s);
566+
CallbackResult execute(TriggerPtr&& t, const Sync& s);
559567

560568
private:
561569
CallbackExecuter executer_;
@@ -619,7 +627,7 @@ class Action : public Entity {
619627
/**
620628
* Execute the action.
621629
*/
622-
virtual void operator()(const Sync&, TriggerRegistrar&) = 0;
630+
virtual CallbackResult operator()(const Sync&, TriggerRegistrar&) = 0;
623631

624632
/**
625633
* Return whether this action is a significant action.

runtime/include/cloe/trigger/example_actions.hpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ class Log : public Action {
4141
Log(const std::string& name, LogLevel level, const std::string& msg)
4242
: Action(name), level_(level), msg_(msg) {}
4343
ActionPtr clone() const override { return std::make_unique<Log>(name(), level_, msg_); }
44-
void operator()(const Sync&, TriggerRegistrar&) override { logger()->log(level_, msg_.c_str()); }
44+
CallbackResult operator()(const Sync&, TriggerRegistrar&) override {
45+
logger()->log(level_, msg_.c_str());
46+
return CallbackResult::Ok;
47+
}
4548
bool is_significant() const override { return false; }
4649

4750
protected:
@@ -71,7 +74,7 @@ class Bundle : public Action {
7174
public:
7275
Bundle(const std::string& name, std::vector<ActionPtr>&& actions);
7376
ActionPtr clone() const override;
74-
void operator()(const Sync& s, TriggerRegistrar& r) override;
77+
CallbackResult operator()(const Sync& s, TriggerRegistrar& r) override;
7578
bool is_significant() const override;
7679

7780
protected:
@@ -103,7 +106,7 @@ class Insert : public Action {
103106
public:
104107
Insert(const std::string& name, const Conf& triggers) : Action(name), triggers_(triggers) {}
105108
ActionPtr clone() const override { return std::make_unique<Insert>(name(), triggers_); }
106-
void operator()(const Sync& s, TriggerRegistrar& r) override;
109+
CallbackResult operator()(const Sync& s, TriggerRegistrar& r) override;
107110

108111
protected:
109112
void to_json(Json& j) const override;
@@ -138,7 +141,7 @@ class PushRelease : public Action {
138141
return std::make_unique<PushRelease>(name(), duration_, push_->clone(), release_->clone(),
139142
repr_);
140143
}
141-
void operator()(const Sync&, TriggerRegistrar&) override;
144+
CallbackResult operator()(const Sync&, TriggerRegistrar&) override;
142145

143146
protected:
144147
void to_json(Json& j) const override { j = repr_; }

0 commit comments

Comments
 (0)