1 #ifndef SIPLASPLAS_SIGNALS_EMITTER_HPP 2 #define SIPLASPLAS_SIGNALS_EMITTER_HPP 4 #include <siplasplas/reflection/dynamic/object_manip.hpp> 5 #include <siplasplas/reflection/dynamic/function_pointer.hpp> 6 #include <siplasplas/utility/function_traits.hpp> 7 #include <siplasplas/utility/hash.hpp> 8 #include <siplasplas/reflection/api.hpp> 9 #include "syncsink.hpp" 10 #include "asyncsink.hpp" 12 #include <siplasplas/signals/export.hpp> 88 template<
typename Caller,
typename Function,
typename R,
typename Class,
typename... Args>
89 static std::shared_ptr<const SignalSink>
connect(Caller& caller, R(Class::*source)(Args...), Function
function)
91 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
92 std::shared_ptr<SignalSink> sink{
new SyncSink{caller,
function} };
94 caller.registerConnection(source, sink);
119 template<
typename Caller,
typename Callee,
typename Function,
typename R,
typename Class,
typename... Args>
120 static std::shared_ptr<const SignalSink>
connect(Caller& caller, R(Class::*source)(Args...), Callee& callee, Function
function)
122 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
123 std::shared_ptr<SignalSink> sink{
new SyncSink{caller, callee,
function} };
125 caller.registerConnection(source, sink);
126 callee.registerIncommingConnection(sink);
150 template<
typename Caller,
typename Function,
typename R,
typename Class,
typename... Args>
151 static std::shared_ptr<const SignalSink>
connect_async(Caller& caller, R(Class::*source)(Args...), Function
function)
153 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
154 std::shared_ptr<SignalSink> sink{
new AsyncSink{caller,
function} };
156 caller.registerConnection(source, sink);
178 template<
typename Caller,
typename Callee,
typename Function,
typename R,
typename Class,
typename... Args>
179 static std::shared_ptr<const SignalSink>
connect_async(Caller& caller, R(Class::*source)(Args...), Callee& callee, Function
function)
181 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
182 std::shared_ptr<SignalSink> sink{
new AsyncSink{caller, callee,
function} };
184 caller.registerConnection(source, sink);
185 callee.registerIncommingConnection(sink);
205 template<
typename Caller,
typename Callee,
typename R,
typename... Args>
206 static std::shared_ptr<const SignalSink>
bypass(Caller& caller, R(Caller::*source)(Args...), Callee& callee, R(Callee::*dest)(Args...))
208 static_assert(equal_signature<decltype(source), decltype(dest)>::value,
"Signal vs slot signatures don't match");
209 return connect(caller, source, callee, [&callee, dest](Args... args)
211 emit(callee, dest, args...);
230 template<
typename Caller,
typename Callee,
typename R,
typename... Args>
231 static std::shared_ptr<const SignalSink>
bypass_async(Caller& caller, R(Caller::*source)(Args...), Callee& callee, R(Callee::*dest)(Args...))
233 static_assert(equal_signature<decltype(source), decltype(dest)>::value,
"Signal vs slot signatures don't match");
234 return connect_async(caller, source, callee, [&callee, dest](Args... args)
236 emit(callee, dest, args...);
247 template<
typename Class,
typename R,
typename... FArgs,
typename... Args>
248 static void emit(Class& emitter, R(Class::*
function)(FArgs...), Args&&... args)
250 emitter.invoke(
function, std::forward<Args>(args)...);
267 template<
typename Function,
typename... Args>
268 void invoke(Function
function, Args&&... args)
270 auto it = _connections.find(::
cpp::hash(
function));
272 if(it != _connections.end())
274 auto& sinks = it->second;
276 #ifdef SIPLASPLAS_LOG_SIGNALS 278 static ctti::type_id_t argsTypes[] = {ctti::type_id<decltype(std::forward<Args>(args))>()..., ctti::type_id<void>()};
279 cpp::dynamic_reflection::Object objectArgs[] = {std::forward<Args>(args)..., cpp::dynamic_reflection::Object()};
281 signals::log().debug(
"Emitting signal from @{}. Args (count={})", static_cast<void*>(
this),
sizeof...(args));
283 for(std::size_t i = 0; i <
sizeof...(Args); ++i)
285 signals::log().debug(
286 " Arg({}): value '{}', type '{}'",
288 objectArgs[i].toString(),
294 for(
auto& sink : sinks)
297 std::forward<Args>(args)...
306 std::mutex _lockConnections;
307 std::mutex _lockIncommingConnections;
311 template<
typename Function>
312 void registerConnection(Function
function,
const std::shared_ptr<SignalSink>& sink)
314 std::lock_guard<std::mutex> guard{_lockConnections};
315 _connections[
::cpp::hash(
function)].push_back(sink);
318 void registerIncommingConnection(
const std::shared_ptr<SignalSink>& sink);
352 template<
typename Class>
355 return ::cpp::static_reflection::Class<Class>::fakeObject(
357 [](
const Class&
object,
auto method,
auto&&... args)
395 template<
typename Class>
398 return ::cpp::static_reflection::Class<Class>::fakeObject(
400 [](Class&
object,
auto method,
auto&&... args)
410 #endif // SIPLASPLAS_SIGNALS_EMITTER_HPP Class that can send and receive signals from other emitters.
Definition: emitter.hpp:66
static void emit(Class &emitter, R(Class::*function)(FArgs...), Args &&...args)
Emits a signal on the given emitter.
Definition: emitter.hpp:248
Implements a direct connection to the destination function.
Definition: syncsink.hpp:20
std::unordered_set< Key, Hash< Key >> HashSet
std::set alias using cpp::Hash as hash.
Definition: hash.hpp:249
Definition: canary_allocator.hpp:7
static std::shared_ptr< const SignalSink > connect_async(Caller &caller, R(Class::*source)(Args...), Callee &callee, Function function)
Creates an asynchronous connection between a signal and a function using an specific callee object...
Definition: emitter.hpp:179
static std::shared_ptr< const SignalSink > connect(Caller &caller, R(Class::*source)(Args...), Function function)
Creates a direct connection from the given emitter object to the given function.
Definition: emitter.hpp:89
static std::shared_ptr< const SignalSink > bypass_async(Caller &caller, R(Caller::*source)(Args...), Callee &callee, R(Callee::*dest)(Args...))
Connects two signals asynchronously.
Definition: emitter.hpp:231
std::unordered_map< Key, Value, Hash< Key >> HashTable
std::unordered_map alias using cpp::Hash as hash.
Definition: hash.hpp:240
static std::shared_ptr< const SignalSink > connect(Caller &caller, R(Class::*source)(Args...), Callee &callee, Function function)
Creates a direct connection from the given emitter object to the given function, using an specific ca...
Definition: emitter.hpp:120
constexpr std::size_t hash(const T &value)
Implements a hash function for values of type T.
Definition: hash.hpp:180
static std::shared_ptr< const SignalSink > bypass(Caller &caller, R(Caller::*source)(Args...), Callee &callee, R(Callee::*dest)(Args...))
Connects two signals synchronously.
Definition: emitter.hpp:206
Implements an asynchronous signal sink suited for communication between different threads...
Definition: asyncsink.hpp:23
static std::shared_ptr< const SignalSink > connect_async(Caller &caller, R(Class::*source)(Args...), Function function)
Creates an asynchronous connection between a signal and a function.
Definition: emitter.hpp:151
auto emit(Class &object)
Emits a signal from the given SignalEmitter.
Definition: emitter.hpp:396