};
/**
- * @brief Emits a signal with no parameters.
+ * @brief Emits a signal with parameter pack.
*
- * @SINCE_1_0.0
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- void Emit();
-
- /**
- * @brief Emits a signal with no parameters.
- *
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
+ * @param[in] args The parameter pack
* @return The value returned by the last callback
* @pre Cannot be called from inside the same Signal's Emit methods.
*/
- template<typename Ret>
- Ret EmitReturn()
+ template<typename Ret, typename... Args>
+ Ret EmitReturn(Args... args)
{
Ret returnVal = Ret();
// This is preferable to reducing the connection count while iterating
if(callback)
{
- returnVal = CallbackBase::ExecuteReturn<Ret>(*callback);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
-
- return returnVal;
- }
-
- /**
- * @brief Emits a signal with 1 parameter.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Arg0>
- void Emit(Arg0 arg0)
- {
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute<Arg0>(*callback, arg0);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
- }
-
- /**
- * @brief Emits a signal with 1 parameter.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0>
- Ret EmitReturn(Arg0 arg0)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0>(*callback, arg0);
+ returnVal = CallbackBase::ExecuteReturn<Ret, Args...>(*callback, args...);
}
}
}
/**
- * @brief Emits a signal with 2 parameters.
+ * @brief Emits a signal with parameter pack.
*
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
+ * @SINCE_1_9.33
+ * @param[in] args The parameter pack
* @pre Cannot be called from inside the same Signal's Emit methods.
*/
- template<typename Arg0, typename Arg1>
- void Emit(Arg0 arg0, Arg1 arg1)
+ template<typename... Args>
+ void Emit(Args... args)
{
// Guards against nested Emit() calls
EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
// This is preferable to reducing the connection count while iterating
if(callback)
{
- CallbackBase::Execute<Arg0, Arg1>(*callback, arg0, arg1);
+ CallbackBase::Execute<Args...>(*callback, args...);
}
}
CleanupConnections();
}
- /**
- * @brief Emits a signal with 2 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0, typename Arg1>
- Ret EmitReturn(Arg0 arg0, Arg1 arg1)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0, Arg1>(*callback, arg0, arg1);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
-
- return returnVal;
- }
-
- /**
- * @brief Emits a signal with 3 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @param[in] arg2 The third parameter
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Arg0, typename Arg1, typename Arg2>
- void Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2)
- {
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute<Arg0, Arg1, Arg2>(*callback, arg0, arg1, arg2);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
- }
-
- /**
- * @brief Emits a signal with 3 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @param[in] arg2 The third parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0, typename Arg1, typename Arg2>
- Ret EmitReturn(Arg0 arg0, Arg1 arg1, Arg2 arg2)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.size());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0, Arg1, Arg2>(*callback, arg0, arg1, arg2);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
-
- return returnVal;
- }
-
// Connect / Disconnect function for use by Signal implementations
/**
/**
* @brief Function to call the function or member function dispatcher.
*
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- */
- static void Execute(CallbackBase& callback)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code so the library containing
- // the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- Dispatcher dispatcher = callback.mImpl.mMemberFunctionDispatcher;
- (*dispatcher)(callback);
- }
- // its also possible to have a member function pointer to a CallbackProvider
- // that has been deleted, so check if we have impl still
- else if(callback.mFunction)
- {
- (*(callback.mFunction))();
- }
- else
- {
- DALI_ASSERT_ALWAYS(0 && "no function to execute");
- }
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @return The value from the function
- */
- template<typename R>
- static R ExecuteReturn(CallbackBase& callback)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code so the library containing
- // the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback);
- }
- else if(callback.mFunction)
- {
- using Function1 = R (*)();
- returnVal = (*(reinterpret_cast<Function1>(callback.mFunction)))();
- }
-
- return returnVal;
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
* This function template gets instantiated at the call site.
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- */
- template<typename P1>
- static void Execute(CallbackBase& callback, P1 param1)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- using Dispatcher = void (*)(CallbackBase&, P1);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1);
- }
- else if(callback.mFunction)
- {
- // convert function type
- using Function1 = void (*)(P1);
- (*(reinterpret_cast<Function1>(callback.mFunction)))(param1);
- }
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
+ * @param[in] args parameter pack to pass into the function
* @return The value from the function
*/
- template<typename R, typename P1>
- static R ExecuteReturn(CallbackBase& callback, P1 param1)
+ template<typename R, typename... Args>
+ static R ExecuteReturn(CallbackBase& callback, Args... args)
{
R returnVal = R();
// if we point to a function, we can call it directly
// so the library containing the code has to be loaded, otherwise we crash boom bang
if(callback.mImpl.mObjectPointer)
{
- using Dispatcher = R (*)(CallbackBase&, P1);
+ using Dispatcher = R (*)(CallbackBase&, Args...);
Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1);
+ returnVal = (*dispatcher)(callback, args...);
}
else if(callback.mFunction)
{
// convert function type
- using Function1 = R (*)(P1);
- returnVal = (*(reinterpret_cast<Function1>(callback.mFunction)))(param1);
+ using Function = R (*)(Args...);
+ returnVal = (*(reinterpret_cast<Function>(callback.mFunction)))(args...);
}
return returnVal;
* @brief Function to call the function or member function dispatcher.
*
* This function template gets instantiated at the call site.
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
+ * @param[in] args parameter pack to pass into the function
*/
- template<typename P1, typename P2>
- static void Execute(CallbackBase& callback, P1 param1, P2 param2)
+ template<typename... Args>
+ static void Execute(CallbackBase& callback, Args... args)
{
// if we point to a function, we can call it directly
// otherwise call the dispatcher function that knows the real type of the object
// so the library containing the code has to be loaded, otherwise we crash boom bang
if(callback.mImpl.mObjectPointer)
{
- using Dispatcher = void (*)(CallbackBase&, P1, P2);
+ using Dispatcher = void (*)(CallbackBase&, Args...);
Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1, param2);
+ (*dispatcher)(callback, args...);
}
else if(callback.mFunction)
{
// convert function type
- using Function2 = void (*)(P1, P2);
- (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2);
+ using Function = void (*)(Args...);
+ (*(reinterpret_cast<Function>(callback.mFunction)))(args...);
}
}
+public:
/**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @return The return value from the function
- */
- template<typename R, typename P1, typename P2>
- static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&, P1, P2);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1, param2);
- }
- else if(callback.mFunction)
- {
- // convert function type
- using Function2 = R (*)(P1, P2);
- returnVal = (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2);
- }
-
- return returnVal;
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
+ * @brief Function with static linkage.
* @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @param[in] param3 The third parameter to pass into the function
*/
- template<typename P1, typename P2, typename P3>
- static void Execute(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- using Dispatcher = void (*)(CallbackBase&, P1, P2, P3);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1, param2, param3);
- }
- else if(callback.mFunction)
- {
- // convert function type
- using Function2 = void (*)(P1, P2, P3);
- (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2, param3);
- }
- }
+ using Function = void (*)();
/**
- * @brief Function to call the function or member function dispatcher.
+ * @brief Constructor for function with static linkage.
*
- * This function template gets instantiated at the call site.
* @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @param[in] param3 The third parameter to pass into the function
- * @return The return value from the function
+ * @param[in] function The function to call
*/
- template<typename R, typename P1, typename P2, typename P3>
- static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl.mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&, P1, P2, P3);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1, param2, param3);
- }
- else if(callback.mFunction)
- {
- // convert function type
- using Function2 = R (*)(P1, P2, P3);
- returnVal = (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2, param3);
- }
-
- return returnVal;
- }
+ CallbackBase(Function function);
protected: // Constructors for deriving classes
- /**
- * @brief Function with static linkage.
- * @SINCE_1_0.0
- */
- using Function = void (*)();
+
/**
* @brief Member function.
CallbackBase& operator=(const CallbackBase& rhs);
/**
- * @brief Constructor for function with static linkage.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- */
- CallbackBase(Function function);
-
- /**
* @brief Constructor for member function.
*
* @SINCE_1_0.0
};
/**
- * @brief Specializations for static function callbacks.
- * @SINCE_1_0.0
- */
-class CallbackFunction : public CallbackBase
-{
-public:
- /**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- CallbackFunction()
- : CallbackBase()
- {
- }
-
- /**
- * @brief Constructors for functions with static linkage.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- */
- CallbackFunction(void (*function)())
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename R>
- CallbackFunction(R (*function)())
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1>
- CallbackFunction(void (*function)(P1))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename R>
- CallbackFunction(R (*function)(P1))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2>
- CallbackFunction(void (*function)(P1, P2))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename R>
- CallbackFunction(R (*function)(P1, P2))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename P3>
- CallbackFunction(void (*function)(P1, P2, P3))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename P3, typename R>
- CallbackFunction(R (*function)(P1, P2, P3))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
-};
-
-/**
* @brief Specializations for function object callbacks.
* @SINCE_1_0.0
*/
// Callback creation thin templates
/**
- * @brief Creates a callback from a C function or static member function with no parameters.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-inline CallbackBase* MakeCallback(void (*function)(void))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with one parameter.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1>
-inline CallbackBase* MakeCallback(void (*function)(P1))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with no parameters and a return type.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R>
-inline CallbackBase* MakeCallback(R (*function)(void))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with one parameter and a return type.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R, typename P1>
-inline CallbackBase* MakeCallback(R (*function)(P1))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with two parameters.
+ * @brief Creates a callback from a free function with parameter pack.
*
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1, typename P2>
-inline CallbackBase* MakeCallback(void (*function)(P1, P2))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with two parameters and a return type.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R, typename P1, typename P2>
-inline CallbackBase* MakeCallback(R (*function)(P1, P2))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with three parameters.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1, typename P2, typename P3>
-inline CallbackBase* MakeCallback(void (*function)(P1, P2, P3))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with three parameters and a return type.
- *
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] function The function to call
* @return A newly allocated Callback object, ownership transferred to caller
*/
-template<typename R, typename P1, typename P2, typename P3>
-inline CallbackBase* MakeCallback(R (*function)(P1, P2, P3))
+template<typename R, typename... Args>
+inline CallbackBase* MakeCallback(R (*function)(Args... args))
{
- return new CallbackFunction(function);
+ return new CallbackBase(reinterpret_cast<CallbackBase::Function>(function));
}
/**