diff --git a/esignal/Signal.h b/esignal/Signal.h index 83d3649..7d704c5 100644 --- a/esignal/Signal.h +++ b/esignal/Signal.h @@ -24,18 +24,15 @@ namespace esignal { * @brief Basic signal base * @param[in] Args... Argument of the signal */ - template + template class Signal : public esignal::Base { public: - using Observer = std::function; //!< Define an Observer: function pointer + using Observer = std::function; //!< Define an Observer: function pointer protected: int32_t m_callInProgress; //!< know if we are in a recursive loop public: //! @brief Basic constructor - Signal(): - m_callInProgress(0) { - - } + Signal(); //! @brief Copy constructor (REMOVED) Signal(const Signal&) = delete; //! @brief Copy operator (REMOVED) @@ -59,12 +56,7 @@ namespace esignal { * @brief Basic constructor. * @param[in] _observer Observer to call. */ - Executor(Observer&& _observer): - m_removed(false), - m_uid(0) { - m_uid = s_uid++; - m_observer = std::move(_observer); - } + Executor(Observer&& _observer); //! @brief virtual destructor. virtual ~Executor() = default; public: @@ -72,28 +64,16 @@ namespace esignal { * @brief Emit the data on the observer. * @param[in] _values... Multiple value needed to send on observers */ - virtual void emit(const Args&... _values) { - if (m_removed == true) { - return; - } - try { - m_observer(_values...); - } catch(...) { - m_removed = true; - std::cout << "LOL"<< std::endl; - } - } + virtual void emit(const T_ARGS&... _values); public: - virtual bool isSharedPtr(const std::shared_ptr& _obj) { - return false; - } + virtual bool isSharedPtr(const std::shared_ptr& _obj); }; protected: std::vector> m_executors; //!< List of all executors. private: /** * @brief Executor specific to the Shared_ptr caller that does not want to worry about the removing of the signal. - * @param[in] Args... Argument of the signal + * @param[in] T_ARGS... Argument of the signal */ class ExecutorShared : public Executor { protected: @@ -104,44 +84,15 @@ namespace esignal { * @param[in] _object A weak reference of the object. * @param[in] _observer Observer to call. */ - ExecutorShared(std::weak_ptr _object, Observer&& _observer) : - Executor(std::move(_observer)), - m_object(_object) { - - } + ExecutorShared(std::weak_ptr _object, Observer&& _observer); public: /** * @brief Emit the data on the observer. * @param[in] _values... Multiple value needed to send on observers */ - virtual void emit(const Args&... _values) { - // TODO: maybe an error if the object is not manage by the same thread. - std::shared_ptr destObject = m_object.lock(); - if (destObject == nullptr) { - Executor::m_removed = true; - return; - } - if (Executor::m_removed == true) { - return; - } - try { - Executor::m_observer(_values...); - } catch(...) { - Executor::m_removed = true; - std::cout << "LOL"<< std::endl; - } - } + virtual void emit(const T_ARGS&... _values); public: - virtual bool isSharedPtr(const std::shared_ptr& _obj) { - std::shared_ptr destObject = m_object.lock(); - if (destObject == nullptr) { - return true; - } - if (destObject == _obj) { - return true; - } - return false; - } + virtual bool isSharedPtr(const std::shared_ptr& _obj); }; public: /** @@ -163,7 +114,7 @@ namespace esignal { */ template Connection connect(classType* _class, Func _func, Arg... _arg) { - std::unique_ptr executer(new Executor([=](const Args& ... _argBase){ + std::unique_ptr executer(new Executor([=](const T_ARGS& ... _argBase){ (*_class.*_func)(_argBase..., _arg... ); })); std::size_t uid = executer->m_uid; @@ -177,14 +128,14 @@ namespace esignal { * @param[in] _arg Argument optinnal the user want to add. */ template - void connect(const std::shared_ptr& _class, void (TYPE::*_func)(const Args&..., Arg...), Arg... _args) { + void connect(const std::shared_ptr& _class, void (TYPE::*_func)(const T_ARGS&..., Arg...), Arg... _args) { std::shared_ptr obj2 = std::dynamic_pointer_cast(_class); if (obj2 == nullptr) { ESIGNAL_ERROR("Can not bind signal ..."); return; } TYPE* directPointer = obj2.get(); - std::unique_ptr executer(new ExecutorShared(_class, [=]( const Args& ... _argBase){ + std::unique_ptr executer(new ExecutorShared(_class, [=]( const T_ARGS& ... _argBase){ // TODO : Check if compilator does not use the shared ptr ... (*directPointer.*_func)(_argBase..., _args... ); })); @@ -195,81 +146,31 @@ namespace esignal { * @brief Emit data on the signal. * @param[in] _args Argument data to emit. */ - template< class... CallArgs> - void emit(CallArgs&&... _args) { - // TODO : Add protection ... but how ... - m_callInProgress++; - for (size_t iii=0; iii < m_executors.size(); ++iii) { - m_executors[iii]->emit(_args...); - } - if (m_callInProgress == 1) { - auto it = m_executors.begin(); - while (it != m_executors.end()) { - if ( *it == nullptr - || (*it)->m_removed == true) { - it = m_executors.erase(it); - continue; - } - ++it; - } - } - m_callInProgress--; - } + void emit(const T_ARGS&... _args); protected: - void removeIfPossible() { - auto it = m_executors.begin(); - while (it != m_executors.end()) { - if ( *it == nullptr - || (*it)->m_removed == true) { - it = m_executors.erase(it); - continue; - } - ++it; - } - } + void removeIfPossible(); public: /** * @brief Disconnect an observer of the signal. * @param[in] _uid Unique id of the signal. */ - void disconnect(std::size_t _uid) { - for (size_t iii=0; iii < m_executors.size(); ++iii) { - if (m_executors[iii]->m_uid == _uid) { - m_executors[iii]->m_removed = true; - break; - } - } - removeIfPossible(); - } - void disconnectShared(const std::shared_ptr& _obj) { - for (size_t iii=0; iii < m_executors.size(); ++iii) { - if (m_executors[iii]->isSharedPtr(_obj) == true) { - m_executors[iii]->m_removed = true; - } - } - removeIfPossible(); - } + void disconnect(std::size_t _uid); + void disconnectShared(const std::shared_ptr& _obj); /** * @brief Get the number of observers connected on the signal. * @return The count of observer. */ - size_t size() const { - return m_executors.size(); - } + size_t size() const; /** * @brief Check if we have a connected observers. * @return true More than one observers. * @return false No observers. */ - bool empty() const { - return m_executors.empty(); - } + bool empty() const; /** * @brief Clear all connectd observers. */ - void clear() { - m_executors.clear(); - } + void clear(); }; } diff --git a/esignal/details/Signal.cpp b/esignal/details/Signal.cpp index 7df9fdf..abc319f 100644 --- a/esignal/details/Signal.cpp +++ b/esignal/details/Signal.cpp @@ -15,9 +15,8 @@ size_t esignal::s_uid = 0; #undef __class__ #define __class__ "Signal" -#if 0 // void generic signal -//template class esignal::Signal; +template class esignal::Signal<>; // std generic signal template class esignal::Signal; template class esignal::Signal; @@ -52,5 +51,3 @@ template class esignal::Signal>; template class esignal::Signal>; template class esignal::Signal>; template class esignal::Signal>; - -#endif diff --git a/esignal/details/Signal.hxx b/esignal/details/Signal.hxx index be45f26..182fdbf 100644 --- a/esignal/details/Signal.hxx +++ b/esignal/details/Signal.hxx @@ -12,7 +12,159 @@ #include #undef __class__ -#define __class__ "Signal" +#define __class__ "Signal" + + +template +esignal::Signal::Signal(): + m_callInProgress(0) { + // nothing to do +} + +template +void esignal::Signal::emit(const T_ARGS&... _args) { + // TODO : Add protection ... but how ... + m_callInProgress++; + for (size_t iii=0; iii < m_executors.size(); ++iii) { + m_executors[iii]->emit(_args...); + } + if (m_callInProgress == 1) { + auto it = m_executors.begin(); + while (it != m_executors.end()) { + if ( *it == nullptr + || (*it)->m_removed == true) { + it = m_executors.erase(it); + continue; + } + ++it; + } + } + m_callInProgress--; +} + +template +void esignal::Signal::removeIfPossible() { + auto it = m_executors.begin(); + while (it != m_executors.end()) { + if ( *it == nullptr + || (*it)->m_removed == true) { + it = m_executors.erase(it); + continue; + } + ++it; + } +} + +template +void esignal::Signal::disconnect(std::size_t _uid) { + for (size_t iii=0; iii < m_executors.size(); ++iii) { + if (m_executors[iii]->m_uid == _uid) { + m_executors[iii]->m_removed = true; + break; + } + } + removeIfPossible(); +} + +template +void esignal::Signal::disconnectShared(const std::shared_ptr& _obj) { + for (size_t iii=0; iii < m_executors.size(); ++iii) { + if (m_executors[iii]->isSharedPtr(_obj) == true) { + m_executors[iii]->m_removed = true; + } + } + removeIfPossible(); +} + +template +size_t esignal::Signal::size() const { + return m_executors.size(); +} + +template +bool esignal::Signal::empty() const { + return m_executors.empty(); +} + +template +void esignal::Signal::clear() { + m_executors.clear(); +} + + +template +esignal::Signal::Executor::Executor(Observer&& _observer): + m_removed(false), + m_uid(0) { + m_uid = s_uid++; + m_observer = std::move(_observer); +} + +template +void esignal::Signal::Executor::emit(const T_ARGS&... _values) { + if (m_removed == true) { + return; + } + try { + m_observer(_values...); + } catch(...) { + m_removed = true; + std::cout << "LOL"<< std::endl; + } +} + +template +bool esignal::Signal::Executor::isSharedPtr(const std::shared_ptr& _obj) { + return false; +} + + + + +template +esignal::Signal::ExecutorShared::ExecutorShared(std::weak_ptr _object, Observer&& _observer) : + Executor(std::move(_observer)), + m_object(_object) { + +} + +template +void esignal::Signal::ExecutorShared::emit(const T_ARGS&... _values) { + // TODO: maybe an error if the object is not manage by the same thread. + std::shared_ptr destObject = m_object.lock(); + if (destObject == nullptr) { + Executor::m_removed = true; + return; + } + if (Executor::m_removed == true) { + return; + } + try { + Executor::m_observer(_values...); + } catch(...) { + Executor::m_removed = true; + std::cout << "LOL"<< std::endl; + } +} + +template +bool esignal::Signal::ExecutorShared::isSharedPtr(const std::shared_ptr& _obj) { + std::shared_ptr destObject = m_object.lock(); + if (destObject == nullptr) { + return true; + } + if (destObject == _obj) { + return true; + } + return false; +} + + + + + + + #if 0 template esignal::Signal::Signal() : m_callInProgress(0), @@ -24,7 +176,7 @@ template esignal::Signal::~Signal() { } -template void esignal::Signal::connect(std::shared_ptr _obj, std::function _function ) { + void esignal::Signal::connect(std::shared_ptr _obj, std::function _function ) { if (m_callInProgress == 0) { m_callerList.push_back(std::make_pair(std::weak_ptr(_obj), _function)); } else { diff --git a/lutin_esignal-test.py b/lutin_esignal-test.py index 28044cf..87294f0 100644 --- a/lutin_esignal-test.py +++ b/lutin_esignal-test.py @@ -29,6 +29,7 @@ def create(target, module_name): my_module = module.Module(__file__, module_name, get_type()) my_module.add_src_file([ 'test/main.cpp', + 'test/declareSignals.cpp', 'test/test_signal_class_func.cpp', 'test/test_signal_recursive.cpp', 'test/test_signal_shared_ptr_func.cpp',