1 #ifndef SIPLASPLAS_SIGNALS_EMITTER_HPP 2 #define SIPLASPLAS_SIGNALS_EMITTER_HPP 4 #include <siplasplas/utility/function_traits.hpp> 5 #include <siplasplas/utility/hash.hpp> 6 #include <siplasplas/reflection/static/api.hpp> 7 #include "syncsink.hpp" 8 #include "asyncsink.hpp" 10 #include <siplasplas/signals/export.hpp> 86 template<
typename Caller,
typename Function,
typename R,
typename Class,
typename... Args>
87 static std::shared_ptr<const SignalSink>
connect(Caller& caller, R(Class::*source)(Args...), Function
function)
89 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
90 std::shared_ptr<SignalSink> sink{
new SyncSink{caller,
function} };
92 caller.registerConnection(source, sink);
117 template<
typename Caller,
typename Callee,
typename Function,
typename R,
typename Class,
typename... Args>
118 static std::shared_ptr<const SignalSink>
connect(Caller& caller, R(Class::*source)(Args...), Callee& callee, Function
function)
120 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
121 std::shared_ptr<SignalSink> sink{
new SyncSink{caller, callee,
function} };
123 caller.registerConnection(source, sink);
124 callee.registerIncommingConnection(sink);
148 template<
typename Caller,
typename Function,
typename R,
typename Class,
typename... Args>
149 static std::shared_ptr<const SignalSink>
connect_async(Caller& caller, R(Class::*source)(Args...), Function
function)
151 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
152 std::shared_ptr<SignalSink> sink{
new AsyncSink{caller,
function} };
154 caller.registerConnection(source, sink);
176 template<
typename Caller,
typename Callee,
typename Function,
typename R,
typename Class,
typename... Args>
177 static std::shared_ptr<const SignalSink>
connect_async(Caller& caller, R(Class::*source)(Args...), Callee& callee, Function
function)
179 static_assert(equal_signature<decltype(source), Function>::value,
"Signal vs slot signatures don't match");
180 std::shared_ptr<SignalSink> sink{
new AsyncSink{caller, callee,
function} };
182 caller.registerConnection(source, sink);
183 callee.registerIncommingConnection(sink);
203 template<
typename Caller,
typename Callee,
typename R,
typename... Args>
204 static std::shared_ptr<const SignalSink>
bypass(Caller& caller, R(Caller::*source)(Args...), Callee& callee, R(Callee::*dest)(Args...))
206 static_assert(equal_signature<decltype(source), decltype(dest)>::value,
"Signal vs slot signatures don't match");
207 return connect(caller, source, callee, [&callee, dest](Args... args)
209 emit(callee, dest, args...);
228 template<
typename Caller,
typename Callee,
typename R,
typename... Args>
229 static std::shared_ptr<const SignalSink>
bypass_async(Caller& caller, R(Caller::*source)(Args...), Callee& callee, R(Callee::*dest)(Args...))
231 static_assert(equal_signature<decltype(source), decltype(dest)>::value,
"Signal vs slot signatures don't match");
232 return connect_async(caller, source, callee, [&callee, dest](Args... args)
234 emit(callee, dest, args...);
245 template<
typename Class,
typename R,
typename... FArgs,
typename... Args>
246 static void emit(Class& emitter, R(Class::*
function)(FArgs...), Args&&... args)
248 emitter.invoke(
function, std::forward<Args>(args)...);
265 template<
typename Function,
typename... Args>
266 void invoke(Function
function, Args&&... args)
268 auto it = _connections.find(::
cpp::hash(
function));
270 if(it != _connections.end())
272 auto& sinks = it->second;
274 #ifdef SIPLASPLAS_LOG_SIGNALS 276 static ctti::type_id_t argsTypes[] = {ctti::type_id<decltype(std::forward<Args>(args))>()..., ctti::type_id<void>()};
278 signals::log().debug(
"Emitting signal from @{}. Args (count={})", static_cast<void*>(
this),
sizeof...(args));
280 for(std::size_t i = 0; i <
sizeof...(Args); ++i)
282 signals::log().debug(
283 " Arg({}): value '{}', type '{}'",
290 for(
auto& sink : sinks)
293 std::forward<Args>(args)...
302 std::mutex _lockConnections;
303 std::mutex _lockIncommingConnections;
307 template<
typename Function>
308 void registerConnection(Function
function,
const std::shared_ptr<SignalSink>& sink)
310 std::lock_guard<std::mutex> guard{_lockConnections};
311 _connections[
::cpp::hash(
function)].push_back(sink);
314 void registerIncommingConnection(
const std::shared_ptr<SignalSink>& sink);
348 template<
typename Class>
351 return ::cpp::static_reflection::Class<Class>::fakeObject(
353 [](
const Class&
object,
auto method,
auto&&... args)
391 template<
typename Class>
394 return ::cpp::static_reflection::Class<Class>::fakeObject(
396 [](Class&
object,
auto method,
auto&&... args)
406 #endif // SIPLASPLAS_SIGNALS_EMITTER_HPP Class that can send and receive signals from other emitters.
Definition: emitter.hpp:64
static void emit(Class &emitter, R(Class::*function)(FArgs...), Args &&...args)
Emits a signal on the given emitter.
Definition: emitter.hpp:246
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:177
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:87
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:229
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:118
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:204
decltype(auto) invoke(Callable &&callable, const ::cpp::SimpleAny< Storages > &...args)
Invokes a callable object with the given type-erased arguments.
Definition: invoke.hpp:214
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:149
auto emit(Class &object)
Emits a signal from the given SignalEmitter.
Definition: emitter.hpp:392