Skip to content

Commit f8920a3

Browse files
committed
compose callbacks instead of using a vector of callbacks
1 parent abcc3c3 commit f8920a3

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

include/reactor-cpp/port.hh

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <vector>
1414

1515
#include "assert.hh"
16+
#include "fwd.hh"
1617
#include "multiport.hh"
1718
#include "reactor.hh"
1819
#include "value_ptr.hh"
@@ -31,7 +32,7 @@ private:
3132
std::set<Reaction*> triggers_{};
3233
std::set<Reaction*> anti_dependencies_{};
3334

34-
std::vector<PortCallback> set_callbacks_{};
35+
PortCallback set_callback_{nullptr};
3536
PortCallback clean_callback_{nullptr};
3637

3738
protected:
@@ -58,8 +59,8 @@ protected:
5859
}
5960

6061
inline void invoke_set_callback() noexcept {
61-
for (auto& callback : set_callbacks_) {
62-
callback(*this);
62+
if (set_callback_ != nullptr) {
63+
set_callback_(*this);
6364
}
6465
}
6566

@@ -92,12 +93,8 @@ public:
9293
[[nodiscard]] inline auto anti_dependencies() const noexcept -> const auto& { return anti_dependencies_; }
9394
[[nodiscard]] inline auto port_type() const noexcept -> PortType { return type_; }
9495

95-
void register_set_callback(const PortCallback& callback) { set_callbacks_.emplace_back(callback); }
96-
97-
void register_clean_callback(const PortCallback& callback) {
98-
reactor_assert(clean_callback_ == nullptr);
99-
clean_callback_ = callback;
100-
}
96+
void register_set_callback(const PortCallback& callback);
97+
void register_clean_callback(const PortCallback& callback);
10198

10299
friend class Reaction;
103100
friend class Scheduler;

lib/port.cc

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,41 @@ auto Port<void>::typed_inward_binding() const noexcept -> Port<void>* {
9494
}
9595

9696
void Port<void>::set() {
97-
validate(!has_inward_binding(), "set() may only be called on a ports that do not have an inward "
97+
validate(!has_inward_binding(), "set() may only be called on ports that do not have an inward "
9898
"binding!");
9999

100100
auto* scheduler = environment()->scheduler();
101101
scheduler->set_port(this);
102102
this->present_ = true;
103103
}
104104

105+
// This function can be used to chain two callbacks. This mechanism is not
106+
// very efficient if many callbacks are registered on the same port. However,
107+
// it is more efficient than, e.g., a vector of callbacks if usually only one
108+
// callback is registered. At the moment, we use at most two callbacks on the
109+
// same port (one if the port is in a multiport, and one if it is upstream of
110+
// a delayed connection).
111+
auto compose_callbacks(const PortCallback& callback1, const PortCallback& callback2) -> PortCallback {
112+
return [=](const BasePort& port) {
113+
callback1(port);
114+
callback2(port);
115+
};
116+
}
117+
118+
void BasePort::register_set_callback(const PortCallback& callback) {
119+
if (set_callback_ == nullptr) {
120+
set_callback_ = callback;
121+
} else {
122+
set_callback_ = compose_callbacks(set_callback_, callback);
123+
}
124+
}
125+
126+
void BasePort::register_clean_callback(const PortCallback& callback) {
127+
if (clean_callback_ == nullptr) {
128+
clean_callback_ = callback;
129+
} else {
130+
clean_callback_ = compose_callbacks(clean_callback_, callback);
131+
}
132+
}
133+
105134
} // namespace reactor

0 commit comments

Comments
 (0)