diff --git a/esignal/Base.cpp b/esignal/Base.cpp index a5c8a7c..695c48a 100644 --- a/esignal/Base.cpp +++ b/esignal/Base.cpp @@ -11,31 +11,57 @@ #include #include -size_t esignal::Base::s_uid = 1; -int64_t esignal::Base::s_uidSignalEmit = 1; +size_t esignal::BaseInternal::s_uid = 1; +int64_t esignal::BaseInternal::s_uidSignalEmit = 1; -esignal::Base::Base(ObserverConnection _countObs) : - m_shared(this), - m_connectionObserver(_countObs) { +void esignal::BaseInternal::setPeriodic(bool _state) { + m_periodic = _state; +} + +const std::string& esignal::BaseInternal::getName() const { + return m_name; +} + +void esignal::BaseInternal::setName(const std::string& _name) { + m_name = _name; +} + +const std::string& esignal::BaseInternal::getDescription() const { + return m_description; +} + +void esignal::BaseInternal::setDescription(const std::string& _desc) { + m_description = _desc; +} + +esignal::Base::Base() : + m_data(nullptr) { } esignal::Base::~Base() { - m_shared.removeData(); + m_data.reset(); } - const std::string& esignal::Base::getName() const { + if (m_data != nullptr) { + return m_data->getName(); + } static std::string noValue; return noValue; } const std::string& esignal::Base::getDescription() const { + if (m_data != nullptr) { + return m_data->getDescription(); + } static std::string noValue; return noValue; } void esignal::Base::setPeriodic(bool _state) { - m_periodic = _state; + if (m_data != nullptr) { + m_data->setPeriodic(_state); + } } std::ostream& esignal::operator <<(std::ostream& _os, const esignal::Base& _obj) { diff --git a/esignal/Base.h b/esignal/Base.h index ba3fbd7..04b813b 100644 --- a/esignal/Base.h +++ b/esignal/Base.h @@ -15,30 +15,93 @@ #include #include #include -#include /** * @brief esignal global interface for all signal implementation */ namespace esignal { - /** - * @brief Base signal interface for esignal::Signal (permit to create abstract list of signals...) - */ - class Base { + class BaseInternal : public ememory::EnableSharedFromThis { public: using ObserverConnection = std::function; //!< Define an Observer of the number of observer protected: bool m_periodic; //!< The signal is periodic ==> no log with this signal ... (no really needed) - esignal::LockSharedPtrRef m_shared; //!< Reference counter on itself. static size_t s_uid; //!< global id of the signal (STATIC) static int64_t s_uidSignalEmit; //!< global id to emit counting - ObserverConnection m_connectionObserver; //!< propriétéry of the connection handle basic + ObserverConnection m_connectionObserver; //!< propriétéry of the connection handle basic + std::string m_name; //!< name of the signal. + std::string m_description; //!< description of the signal. public: /** * @brief Basic constructor: * @param[in] _countObs Observer on the number of connection availlable */ - Base(ObserverConnection _countObs = nullptr); + BaseInternal(ObserverConnection _countObs) : + m_connectionObserver(_countObs) { + + } + virtual ~BaseInternal() = default; + /** + * @brief Disconnect the shared_ptr form the Signal + * @param[in] _obj Link with the object to check + */ + virtual void disconnectShared(const ememory::SharedPtr& _obj) = 0; + /** + * @brief Disconnect an observer of the signal. + * @param[in] _uid Unique id of the signal connection. + */ + virtual void disconnect(size_t _uid) = 0; + /** + * @brief Get name of the signal. + * @return requested name. + */ + const std::string& getName() const; + /** + * @brief Set name of the signal. + * @param[in] _name new name. + */ + void setName(const std::string& _name); + /** + * @brief Get decription of the signal. + * @return requested decription. + */ + const std::string& getDescription() const; + /** + * @brief Set decription of the signal. + * @param[in] _desc new decription. + */ + void setDescription(const std::string& _desc); + /** + * @brief Tag the signal as periodic... + * @param[in] _state state of the periodic element + */ + void setPeriodic(bool _state); + /** + * @brief Get the number of observers connected on the signal. + * @return The count of observer. + */ + virtual size_t size() const = 0; + /** + * @brief Check if we have a connected observers. + * @return true More than one observers. + * @return false No observers. + */ + virtual bool empty() const = 0; + /** + * @brief Clear all connectd observers. + */ + virtual void clear() = 0; + }; + /** + * @brief Base signal interface for esignal::Signal (permit to create abstract list of signals...) + */ + class Base { + protected: + ememory::SharedPtr m_data; + public: + /** + * @brief Basic constructor: + */ + Base(); //! @brief Copy constructor: Base(const Base&) = delete; //! @brief Move constructor @@ -53,11 +116,6 @@ namespace esignal { * @param[in] _obj Link with the object to check */ virtual void disconnectShared(const ememory::SharedPtr& _obj) = 0; - /** - * @brief Disconnect an observer of the signal. - * @param[in] _uid Unique id of the signal connection. - */ - virtual void disconnect(size_t _uid) = 0; /** * @brief Get name of the signal. * @return requested name. diff --git a/esignal/Connection.cpp b/esignal/Connection.cpp index 4f2bda0..50aebc5 100644 --- a/esignal/Connection.cpp +++ b/esignal/Connection.cpp @@ -9,40 +9,55 @@ #include esignal::Connection::Connection(): - m_signalRefUnique(), m_uid(0) { + m_data(nullptr), + m_uid(0) { } -esignal::Connection::Connection(const esignal::LockSharedPtrRef& _ref, size_t _id): - m_signalRefUnique(_ref), +esignal::Connection::Connection(ememory::SharedPtr _ref, size_t _id): + m_data(_ref), m_uid(_id) { } esignal::Connection::Connection(esignal::Connection&& _obj): - m_signalRefUnique(_obj.m_signalRefUnique), + m_data(_obj.m_data), m_uid(_obj.m_uid) { _obj.m_uid = 0; + _obj.m_data.reset(); } esignal::Connection& esignal::Connection::operator=(esignal::Connection&& _obj) { disconnect(); - m_signalRefUnique = _obj.m_signalRefUnique; + m_data = _obj.m_data; m_uid = _obj.m_uid; _obj.m_uid = 0; + _obj.m_data.reset(); return *this; } + esignal::Connection::~Connection() { - m_signalRefUnique.disconnect(m_uid); + ememory::SharedPtr ref = m_data.lock(); + if (ref == nullptr) { + return; + } + ref->disconnect(m_uid); + m_data.reset(); m_uid = 0; } void esignal::Connection::disconnect() { - m_signalRefUnique.disconnect(m_uid); + ememory::SharedPtr ref = m_data.lock(); + if (ref == nullptr) { + return; + } + ref->disconnect(m_uid); + m_data.reset(); m_uid = 0; } bool esignal::Connection::isConnected() { - return m_signalRefUnique.isAlive(); + return m_data.useCount() != 0 + && m_uid != 0; } diff --git a/esignal/Connection.h b/esignal/Connection.h index f84bea1..bdb0267 100644 --- a/esignal/Connection.h +++ b/esignal/Connection.h @@ -17,6 +17,9 @@ namespace esignal { * @brief connection on the signal (disconnect it whe removed) */ class Connection { + private: + ememory::WeakPtr m_data; + size_t m_uid; //!< UID of the current connection. public: /** * @brief Constructor (no link) @@ -27,7 +30,7 @@ namespace esignal { * @param[in] _ref Reference ID of the Signal extern handle * @param[in] _id Id of the Connection handle */ - Connection(const esignal::LockSharedPtrRef& _ref, size_t _id); + Connection(ememory::SharedPtr _ref, size_t _id); /** * @brief Move Constructor * @param[in] _obj Connection Object to move @@ -62,9 +65,6 @@ namespace esignal { * @return false The signal is NOT connected. */ bool isConnected(); - private: - esignal::LockSharedPtrRef m_signalRefUnique; //!< reference on the Signal. - size_t m_uid; //!< UID of the current connection. }; } diff --git a/esignal/ISignal.h b/esignal/ISignal.h deleted file mode 100644 index 33d2121..0000000 --- a/esignal/ISignal.h +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace esignal { - /** - * @brief Sigla same as @ref esignal::Signal withe a name and a description to manage a list of signals. - */ - template - class ISignal : public Signal { - protected: - esignal::Interface* m_signalInterfaceLink; //!< interface of the signal manager. - std::string m_name; //!< name of the signal. - std::string m_description; //!< description of the signal. - public: - /** - * @brief Create a signal with a specific type. - * @param[in] _signalInterfaceLink reference on the signal lister. - * @param[in] _func Local observer to know the count of connection on the signal. - * @param[in] _name Static name of the signal. - * @param[in] _description Description of the signal. - */ - template - ISignal(CLASS_TYPE* _signalInterfaceLink, - FUNC_TYPE _func, - const std::string& _name, - const std::string& _description); - /** - * @brief Create a signal with a specific type. - * @param[in] _signalInterfaceLink reference on the signal lister. - * @param[in] _name Static name of the signal. - * @param[in] _description Description of the signal. - */ - ISignal(esignal::Interface* _signalInterfaceLink, - const std::string& _name, - const std::string& _description); - /** - * @brief Destructor. - */ - virtual ~ISignal(); - const std::string& getName() const override; - const std::string& getDescription() const override; - }; -} - -template -template -esignal::ISignal::ISignal(CLASS_TYPE* _class, - FUNC_TYPE _func, - const std::string& _name, - const std::string& _description) : - esignal::Signal(_class, _func), - m_signalInterfaceLink(_class), - m_name(_name), - m_description(_description) { - // add a reference on the current signal ... - if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signals.add(this); - } -} - diff --git a/esignal/LockSharedPtrRef.h b/esignal/LockSharedPtrRef.h deleted file mode 100644 index 056084f..0000000 --- a/esignal/LockSharedPtrRef.h +++ /dev/null @@ -1,78 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#pragma once - -#include - -namespace esignal { - /** - * @brief shared ptr that permeit to lock access of the internal data (it does not manage the allication and remove of the data). - * @todo Change this with atomic_shared_ptr<> when availlable. - * @param TYPE Type of the internal data - */ - template - class LockSharedPtrRef { - public: - // TODO : Remove data from refcounter ...==> - // esignal::RefCount* m_counter; //!< Access on the reference counter - // TYPE* m_data; //!< Pointer on the data - esignal::RefCount* m_counter; //!< Access on the reference counter - public: - /** - * @brief Basic contructor (with the object to ref count) - * @param[in] _pointer Pointer on the data (default nullptr) - */ - LockSharedPtrRef(TYPE* _pointer=nullptr); - /** - * @brief Copy contructor - * @param[in] _obj object to copy - */ - LockSharedPtrRef(const LockSharedPtrRef& _obj); - /** - * @brief Copy operator (It copy the counter and increment the it). - * @param[in] _obj object to copy. - * @return Reference of this - */ - LockSharedPtrRef& operator=(const LockSharedPtrRef& _obj); - /** - * @brief Contructor (move) - * @param[in] _obj move object - */ - LockSharedPtrRef(LockSharedPtrRef&& _obj); - /** - * @brief Copy operator (force move) ==> removed - * @return Reference of this - */ - LockSharedPtrRef& operator=(LockSharedPtrRef&&) = delete; - /** - * @brief Destructor of the class (decrement the counter and remove it if it is the last one...) - */ - ~LockSharedPtrRef(); - /** - * @brief Remove the data on the conter reference (it does not exist anymore) - */ - void removeData(); - /** - * @brief Call disconnect on the parameter class with lock prevention - * @param[in] _uid ID to dicsonnect on the sub element - */ - void disconnect(size_t _uid); - /** - * @brief Check if the value is availlable - * @return true The data is availlable - * @return false The data has been removed - */ - bool isAlive(); - private: - /** - * @remove reference on the refcounter... - */ - void rmShared(); - }; -} - diff --git a/esignal/RefCount.h b/esignal/RefCount.h deleted file mode 100644 index 6c0aa0a..0000000 --- a/esignal/RefCount.h +++ /dev/null @@ -1,75 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#pragma once - -#include -#include - -namespace esignal { - /** - * @brief Ref counting tool. - */ - template - class RefCount { - private: - std::mutex m_lock; //!< mutex on the refcounting element - int64_t m_count; //!< number of element connected - TYPE* m_data; //!< Pointer on the refconting data - public: - /** - * @brief generic constructor - * @param[in] _data Data to reference the Refcounting - */ - RefCount(TYPE* _data); - //! @brief Copy constructor (REMOVED) - RefCount(const RefCount&) = delete; - /** - * @brief Copy operator (REMOVED) - * @return Reference on this - */ - RefCount& operator=(RefCount) = delete; - /** - * @brief Copy operator (REMOVED) - * @return Reference on this - */ - RefCount& operator=(const RefCount&) = delete; - //! @brief Move constructor (REMOVED) - RefCount(RefCount&&) = delete; - /** - * @brief Move operator (REMOVED) - * @return Reference on this - */ - RefCount& operator=(RefCount&&) = delete; - //! @brief Destructor - ~RefCount(); - public: - //! @brief Lock the interface - void lock(); - //! @brief Unlock the interface - void unlock(); - //! @brief Increment the ref-counting - void inc(); - /** - * @brief Decrement the ref-counting - * @return Number of element connected when decrement - */ - int64_t dec(); - /** - * @brief Get number of connected - * @return The number of element connected on it - */ - int64_t getCount() const; - //! @brief Remove the data - void remove(); - /** - * @brief Get the recoreded data - * @return The pointer of the data - */ - TYPE* get(); - }; -} diff --git a/esignal/Signal.h b/esignal/Signal.h index 62d90b9..a57ce24 100644 --- a/esignal/Signal.h +++ b/esignal/Signal.h @@ -12,53 +12,28 @@ #include #include #include -#include -#include #include +#include +#include namespace esignal { - /** - * @brief Basic signal base - * @param[in] Args... Argument of the signal - */ + template - class Signal : public esignal::Base { + class SignalInternal : public esignal::BaseInternal { public: 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 with connection observer - * @param[in] _countObs Local observer to know the count of connection on the signal. + * @brief Basic constructor: + * @param[in] _countObs Observer on the number of connection availlable */ - Signal(ObserverConnection _countObs=nullptr); - /** - * @brief Basic constructor with connection observer - * @param[in] _class Class which is associated the function to call. - * @param[in] _func Function to call when an observer has connected or disconnected. - */ - template - Signal(CLASS_TYPE* _class, FUNC_TYPE _func); - //! @brief Copy constructor (REMOVED) - Signal(const Signal&) = delete; - /** - * @brief Copy operator (REMOVED) - * @return Reference on this - */ - Signal& operator=(Signal) = delete; - /** - * @brief Copy operator (REMOVED) - * @return Reference on this - */ - Signal& operator=(const Signal&) = delete; - //! @brief Move constructor (REMOVED) - Signal(Signal&&) = delete; - /** - * @brief Move operator (REMOVED) - * @return Reference on this - */ - Signal& operator=(Signal&&) = delete; + SignalInternal(ObserverConnection _countObs): + esignal::BaseInternal(_countObs), + m_callInProgress(0) { + + } private: /** * @brief Executor: Class to manage the UID and basic value of an observer @@ -145,7 +120,6 @@ namespace esignal { void connect(const ememory::SharedPtr& _class, void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), FUNC_ARGS_TYPE... _args); - public: /** * @brief Emit data on the signal. * @param[in] _args Argument data to emit. @@ -158,38 +132,192 @@ namespace esignal { */ void removeIfPossible(); public: - /** - * @brief Disconnect an observer of the signal. - * @param[in] _uid Unique id of the signal connection. - */ void disconnect(size_t _uid) override; + void disconnectShared(const ememory::SharedPtr& _obj) override; + size_t size() const override; + bool empty() const override; + void clear() override; + }; + /** + * @brief Basic signal base + * @param[in] Args... Argument of the signal + */ + template + class Signal : public esignal::Base { + protected: + esignal::Interface* m_signalInterfaceLink; //!< interface of the signal manager. + public: + /** + * @brief Basic constructor with connection observer + * @param[in] _countObs Local observer to know the count of connection on the signal. + * @param[in] _name Static name of the signal. + * @param[in] _description Description of the signal. + */ + Signal(esignal::BaseInternal::ObserverConnection _countObs=nullptr, + const std::string& _name="", + const std::string& _description=""); + /** + * @brief Basic constructor with connection interface + * @param[in] _signalInterfaceLink reference on the signal lister. + * @param[in] _name Static name of the signal. + * @param[in] _description Description of the signal. + */ + Signal(esignal::Interface* _signalInterfaceLink, + const std::string& _name, + const std::string& _description); + /** + * @brief Basic constructor with connection observer + * @param[in] _class Class which is associated the function to call. + * @param[in] _func Function to call when an observer has connected or disconnected. + * @param[in] _name Static name of the signal. + * @param[in] _description Description of the signal. + */ + template::value + , int>::type = 0> + Signal(CLASS_TYPE* _class, + FUNC_TYPE _func, + const std::string& _name, + const std::string& _description); + template::value + , int>::type = 0> + Signal(CLASS_TYPE* _class, + FUNC_TYPE _func, + const std::string& _name="", + const std::string& _description=""); + //! @brief Copy constructor (REMOVED) + Signal(const Signal&) = delete; + /** + * @brief Copy operator (REMOVED) + * @return Reference on this + */ + Signal& operator=(Signal) = delete; + /** + * @brief Copy operator (REMOVED) + * @return Reference on this + */ + Signal& operator=(const Signal&) = delete; + //! @brief Move constructor (REMOVED) + Signal(Signal&&) = delete; + /** + * @brief Move operator (REMOVED) + * @return Reference on this + */ + Signal& operator=(Signal&&) = delete; + /** + * @brief Destructor. + */ + virtual ~Signal(); + public: + /** + * @brief Connect an observer on the signal. + * @param[in] _observer Observer to call. + * @return Connection handle (connection is removed if the handle is destroy) + */ + template< class OBSERVER_TYPE > + esignal::Connection connect(OBSERVER_TYPE&& _observer) { + if (m_data == nullptr) { + return esignal::Connection(); + } + ememory::SharedPtr> pointer = ememory::staticPointerCast>(m_data); + return pointer->connect(std::forward(_observer)); + } + /** + * @brief Connect an function member on the signal. + * @param[in] _class Object on whe we need to call. + * @param[in] _func Function to call. + * @param[in] _args Argument optinnal the user want to add. + * @return Connection handle (connection is removed if the handle is destroy) + */ + template + esignal::Connection connect(CLASS_TYPE* _class, + FUNC_TYPE _func, + FUNC_ARGS_TYPE... _args) { + if (m_data == nullptr) { + return esignal::Connection(); + } + ememory::SharedPtr> pointer = ememory::staticPointerCast>(m_data); + return pointer->connect(_class, _func, std::forward(_args)...); + } + /** + * @brief Connect an function member on the signal with the shared_ptr object. + * @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr. + * @param[in] _func Function to call. + * @param[in] _args Argument optinnal the user want to add. + */ + template + void connect(const ememory::SharedPtr& _class, + void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), + FUNC_ARGS_TYPE... _args) { + if (m_data == nullptr) { + return; + } + ememory::SharedPtr> pointer = ememory::staticPointerCast>(m_data); + return pointer->connect(_class, _func, std::forward(_args)...); + } + public: + /** + * @brief Emit data on the signal. + * @param[in] _args Argument data to emit. + */ + void emit(const T_ARGS&... _args) { + if (m_data == nullptr) { + return; + } + ememory::SharedPtr> pointer = ememory::staticPointerCast>(m_data); + return pointer->emit(std::forward(_args)...); + } + public: /** * @brief Disconnect the shared_ptr form the Signal * @param[in] _obj Link with the object to check */ - void disconnectShared(const ememory::SharedPtr& _obj) override; + void disconnectShared(const ememory::SharedPtr& _obj) override { + if (m_data == nullptr) { + return;; + } + m_data->disconnectShared(_obj); + } /** * @brief Get the number of observers connected on the signal. * @return The count of observer. */ - size_t size() const; + size_t size() const { + if (m_data == nullptr) { + return 0; + } + return m_data->size(); + } /** * @brief Check if we have a connected observers. * @return true More than one observers. * @return false No observers. */ - bool empty() const; + bool empty() const { + if (m_data == nullptr) { + return true; + } + return m_data->empty(); + } /** * @brief Clear all connectd observers. */ - void clear(); + void clear() { + if (m_data == nullptr) { + return; + } + m_data->clear(); + } }; } template template -esignal::Connection esignal::Signal::connect(OBSERVER_TYPE&& _observer ) { +esignal::Connection esignal::SignalInternal::connect(OBSERVER_TYPE&& _observer ) { ESIGNAL_DEBUG("esignal: '" << getName() << "' try connect: '" << getName() << "' (observer)"); std::unique_ptr executer(new Executor(std::forward(_observer))); size_t uid = executer->m_uid; @@ -198,14 +326,14 @@ esignal::Connection esignal::Signal::connect(OBSERVER_TYPE&& _observe m_connectionObserver(m_executors.size()); } ESIGNAL_DEBUG(" '" << getName() << "' new count: " << m_executors.size()); - return esignal::Connection(Base::m_shared, uid); + return esignal::Connection(sharedFromThis(), uid); } template template -esignal::Connection esignal::Signal::connect(CLASS_TYPE* _class, - FUNC_TYPE _func, - FUNC_ARGS_TYPE... _arg) { +esignal::Connection esignal::SignalInternal::connect(CLASS_TYPE* _class, + FUNC_TYPE _func, + FUNC_ARGS_TYPE... _arg) { ESIGNAL_DEBUG("esignal: '" << getName() << "' try connect: '" << getName() << "' (reference)"); if (_class == nullptr) { ESIGNAL_ERROR(" '" << getName() << "' Class pointer in nullptr"); @@ -220,14 +348,14 @@ esignal::Connection esignal::Signal::connect(CLASS_TYPE* _class, m_connectionObserver(m_executors.size()); } ESIGNAL_DEBUG(" '" << getName() << "' new count: " << m_executors.size()); - return Connection(Base::m_shared, uid); + return Connection(sharedFromThis(), uid); } template template -void esignal::Signal::connect(const ememory::SharedPtr& _class, - void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), - FUNC_ARGS_TYPE... _args) { +void esignal::SignalInternal::connect(const ememory::SharedPtr& _class, + void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), + FUNC_ARGS_TYPE... _args) { ESIGNAL_DEBUG("esignal: '" << getName() << "' try connect: '" << getName() << "' (weak pointer)"); if (_class == nullptr) { ESIGNAL_ERROR(" '" << getName() << "' Class pointer in nullptr"); @@ -251,10 +379,54 @@ void esignal::Signal::connect(const ememory::SharedPtr -template +template::value + , int>::type> esignal::Signal::Signal(CLASS_TYPE* _class, - FUNC_TYPE _func): - esignal::Base([=](size_t _val){(*_class.*_func)(_val);}), - m_callInProgress(0) { + FUNC_TYPE _func, + const std::string& _name, + const std::string& _description): + m_signalInterfaceLink(nullptr) { // nothing to do + if (_func != nullptr) { + esignal::Base::m_data = ememory::makeShared>([=](size_t _val){(*_class.*_func)(_val);}); + } else { + esignal::Base::m_data = ememory::makeShared>(nullptr); + } + if (esignal::Base::m_data != nullptr) { + esignal::Base::m_data->setName(_name); + esignal::Base::m_data->setDescription(_description); + } + m_signalInterfaceLink = _class; + // add a reference on the current signal ... + if (m_signalInterfaceLink != nullptr) { + m_signalInterfaceLink->signals.add(this); + } } +template +template::value + , int>::type> +esignal::Signal::Signal(CLASS_TYPE* _class, + FUNC_TYPE _func, + const std::string& _name, + const std::string& _description): + m_signalInterfaceLink(nullptr) { + // nothing to do + if (_func != nullptr) { + esignal::Base::m_data = ememory::makeShared>([=](size_t _val){(*_class.*_func)(_val);}); + } else { + esignal::Base::m_data = ememory::makeShared>(nullptr); + } + if (esignal::Base::m_data != nullptr) { + esignal::Base::m_data->setName(_name); + esignal::Base::m_data->setDescription(_description); + } +} + +#define ESIGNAL_DECLARE_SIGNAL(...) \ + template class esignal::Signal<__VA_ARGS__>; \ + template class esignal::SignalInternal<__VA_ARGS__>; + diff --git a/esignal/details/ISignal.cpp b/esignal/details/ISignal.cpp deleted file mode 100644 index bfdea6c..0000000 --- a/esignal/details/ISignal.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#include -#include -#include -#include -#include - -// void generic signal -template class esignal::ISignal<>; -// std generic signal -template class esignal::ISignal; -template class esignal::ISignal; -#if __CPP_VERSION__ >= 2011 - template class esignal::ISignal; -#endif - -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; - -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; - -template class esignal::ISignal; -template class esignal::ISignal; -// etk generic vetor 2D -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -// etk generic vetor 3D -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -template class esignal::ISignal; -// etk generic color -template class esignal::ISignal>; -template class esignal::ISignal>; -template class esignal::ISignal>; -template class esignal::ISignal>; diff --git a/esignal/details/ISignal.hxx b/esignal/details/ISignal.hxx deleted file mode 100644 index 4df5637..0000000 --- a/esignal/details/ISignal.hxx +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#pragma once - -#include -#include - -template -esignal::ISignal::ISignal(esignal::Interface* _signalInterfaceLink, - const std::string& _name, - const std::string& _description): - m_signalInterfaceLink(_signalInterfaceLink), - m_name(_name), - m_description(_description) { - // add a reference on the current signal ... - if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signals.add(this); - } -} - -template -esignal::ISignal::~ISignal() { - if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signals.remove(this); - } -} - -template -const std::string& esignal::ISignal::getName() const { - return m_name; -} - -template -const std::string& esignal::ISignal::getDescription() const { - return m_description; -} - diff --git a/esignal/details/LockSharedPtrRef.cpp b/esignal/details/LockSharedPtrRef.cpp deleted file mode 100644 index 72fb49e..0000000 --- a/esignal/details/LockSharedPtrRef.cpp +++ /dev/null @@ -1,16 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ - -#include -#include -#include - -// only one really needed ... -template class esignal::LockSharedPtrRef; - - diff --git a/esignal/details/LockSharedPtrRef.hxx b/esignal/details/LockSharedPtrRef.hxx deleted file mode 100644 index 62f182f..0000000 --- a/esignal/details/LockSharedPtrRef.hxx +++ /dev/null @@ -1,117 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ - -#include -#include - -template -esignal::LockSharedPtrRef::LockSharedPtrRef(TYPE* _pointer) : - m_counter(nullptr) { - ESIGNAL_VERBOSE("LockSharedPtrRef new [START] " << int64_t(_pointer)); - if (_pointer != nullptr) { - m_counter = new RefCount(_pointer); - m_counter->inc(); - } - ESIGNAL_VERBOSE("LockSharedPtrRef new [STOP]"); -} - -template -esignal::LockSharedPtrRef::LockSharedPtrRef(const LockSharedPtrRef& _obj) : - m_counter(_obj.m_counter) { - ESIGNAL_VERBOSE("LockSharedPtrRef new [START] ref ..."); - if (m_counter == nullptr) { - return; - } - m_counter->inc(); - ESIGNAL_VERBOSE("LockSharedPtrRef new [STOP]"); -} - -template -esignal::LockSharedPtrRef& esignal::LockSharedPtrRef::operator=(const esignal::LockSharedPtrRef& _obj) { - ESIGNAL_VERBOSE("LockSharedPtrRef copy [START]"); - if (&_obj == this) { - ESIGNAL_VERBOSE("LockSharedPtrRef copy [STOP] auto-copy"); - return *this; - } - if (m_counter != nullptr) { - m_counter->dec(); - m_counter = nullptr; - } - m_counter = _obj.m_counter; - if (m_counter == nullptr) { - ESIGNAL_VERBOSE("LockSharedPtrRef copy [STOP] no counter"); - return *this; - } - m_counter->inc(); - ESIGNAL_VERBOSE("LockSharedPtrRef copy [STOP]"); - return *this; -} - -template -esignal::LockSharedPtrRef::LockSharedPtrRef(LockSharedPtrRef&& _obj) : - m_counter(std::move(_obj.m_counter)) { - ESIGNAL_VERBOSE("LockSharedPtrRef move [DONE]"); -} - -template -esignal::LockSharedPtrRef::~LockSharedPtrRef() { - ESIGNAL_VERBOSE("LockSharedPtrRef delete [START]"); - rmShared(); - ESIGNAL_VERBOSE("LockSharedPtrRef delete [STOP]"); -} - -template -void esignal::LockSharedPtrRef::rmShared() { - ESIGNAL_VERBOSE("LockSharedPtrRef rmShared [START]"); - if (m_counter == nullptr) { - return; - } - int64_t count = m_counter->dec(); - if (count > 0) { - m_counter = nullptr; - return; - } - delete m_counter; - m_counter = nullptr; - ESIGNAL_VERBOSE("LockSharedPtrRef rmShared [STOP]"); -} - -template -void esignal::LockSharedPtrRef::removeData() { - ESIGNAL_VERBOSE("LockSharedPtrRef removeData [START]"); - if (m_counter != nullptr) { - m_counter->remove(); - } - ESIGNAL_VERBOSE("LockSharedPtrRef removeData [STOP]"); -} - -template -void esignal::LockSharedPtrRef::disconnect(size_t _uid) { - ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [START] " << _uid); - if (m_counter == nullptr) { - ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [STOP] No counter"); - return; - } - m_counter->lock(); - TYPE* val = m_counter->get(); - if (val != nullptr) { - val->disconnect(_uid); - } - m_counter->unlock(); - rmShared(); - ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [STOP]"); -} - -template -bool esignal::LockSharedPtrRef::isAlive() { - ESIGNAL_VERBOSE("LockSharedPtrRef isAlive [DONE] "); - return m_counter != nullptr; -} - - - diff --git a/esignal/details/RefCount.cpp b/esignal/details/RefCount.cpp deleted file mode 100644 index bf66d11..0000000 --- a/esignal/details/RefCount.cpp +++ /dev/null @@ -1,16 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ - -#include -#include -#include - -// only one really needed ... -template class esignal::RefCount; - - diff --git a/esignal/details/RefCount.hxx b/esignal/details/RefCount.hxx deleted file mode 100644 index c9a1f1d..0000000 --- a/esignal/details/RefCount.hxx +++ /dev/null @@ -1,80 +0,0 @@ -/** @file - * @author Edouard DUPIN - * - * @copyright 2016, Edouard DUPIN, all right reserved - * - * @license APACHE v2.0 (see license file) - */ -#pragma once - -#include -#include - -template -esignal::RefCount::RefCount(TYPE* _data) : - m_count(0), - m_data(_data) { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount New : " << int64_t(_data)); - // nothing to do. -} - -template -esignal::RefCount::~RefCount() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount delete"); - m_data = nullptr; -} - -template -void esignal::RefCount::lock() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount LOCK [START]"); - m_lock.lock(); - ESIGNAL_VERBOSE(int64_t(this) << " RefCount LOCK [STOP]"); -} - -template -void esignal::RefCount::unlock() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount UN-LOCK [START]"); - m_lock.unlock(); - ESIGNAL_VERBOSE(int64_t(this) << " RefCount UN-LOCK [STOP]"); -} - -template -void esignal::RefCount::inc() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount INC [START] " << m_count); - lock(); - m_count++; - unlock(); - ESIGNAL_VERBOSE(int64_t(this) << " RefCount INC [STOP] " << m_count); -} - -template -int64_t esignal::RefCount::dec() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount DEC [START] " << m_count); - int64_t val; - lock(); - m_count--; - val = m_count; - unlock(); - ESIGNAL_VERBOSE(int64_t(this) << " RefCount DEC [STOP] " << m_count); - return val; -} - -template -int64_t esignal::RefCount::getCount() const { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount get count " << m_count); - return m_count; -} - -template -void esignal::RefCount::remove() { - ESIGNAL_VERBOSE(int64_t(this) << " RefCount remove [START]"); - lock(); - m_data = nullptr; - unlock(); - ESIGNAL_VERBOSE(int64_t(this) << " RefCount remove [STOP]"); -} - -template -TYPE* esignal::RefCount::get() { - return m_data; -} \ No newline at end of file diff --git a/esignal/details/Signal.cpp b/esignal/details/Signal.cpp index 00b234b..9bf9285 100644 --- a/esignal/details/Signal.cpp +++ b/esignal/details/Signal.cpp @@ -12,38 +12,39 @@ #include // void generic signal -template class esignal::Signal<>; +ESIGNAL_DECLARE_SIGNAL(); // std generic signal -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(bool); +ESIGNAL_DECLARE_SIGNAL(std::string); #if __CPP_VERSION__ >= 2011 - template class esignal::Signal; + ESIGNAL_DECLARE_SIGNAL(std::u32string); #endif -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(int64_t); +ESIGNAL_DECLARE_SIGNAL(int32_t); +ESIGNAL_DECLARE_SIGNAL(int16_t); +ESIGNAL_DECLARE_SIGNAL(int8_t); -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(uint64_t); +ESIGNAL_DECLARE_SIGNAL(uint32_t); +ESIGNAL_DECLARE_SIGNAL(uint16_t); +ESIGNAL_DECLARE_SIGNAL(uint8_t); -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(float); +ESIGNAL_DECLARE_SIGNAL(double); // etk generic vetor 2D -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(vec2); +ESIGNAL_DECLARE_SIGNAL(bvec2); +ESIGNAL_DECLARE_SIGNAL(ivec2); +ESIGNAL_DECLARE_SIGNAL(uivec2); // etk generic vetor 3D -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(vec3); +ESIGNAL_DECLARE_SIGNAL(bvec3); +ESIGNAL_DECLARE_SIGNAL(ivec3); +ESIGNAL_DECLARE_SIGNAL(uivec3); // etk generic color -template class esignal::Signal>; -template class esignal::Signal>; -template class esignal::Signal>; -template class esignal::Signal>; +ESIGNAL_DECLARE_SIGNAL(etk::Color); +ESIGNAL_DECLARE_SIGNAL(etk::Color); +ESIGNAL_DECLARE_SIGNAL(etk::Color); +ESIGNAL_DECLARE_SIGNAL(etk::Color); + diff --git a/esignal/details/Signal.hxx b/esignal/details/Signal.hxx index 7c3c2f7..3d9a770 100644 --- a/esignal/details/Signal.hxx +++ b/esignal/details/Signal.hxx @@ -9,15 +9,46 @@ #include -template -esignal::Signal::Signal(ObserverConnection _countObs): - esignal::Base(_countObs), - m_callInProgress(0) { - // nothing to do +template +esignal::Signal::~Signal() { + if (m_signalInterfaceLink != nullptr) { + m_signalInterfaceLink->signals.remove(this); + } } template -void esignal::Signal::emit(const T_ARGS&... _args) { +esignal::Signal::Signal(esignal::BaseInternal::ObserverConnection _countObs, + const std::string& _name, + const std::string& _description): + esignal::Base(), + m_signalInterfaceLink(nullptr) { + // create internal data assiciated: + m_data = ememory::makeShared>(std::move(_countObs)); + if (esignal::Base::m_data != nullptr) { + esignal::Base::m_data->setName(_name); + esignal::Base::m_data->setDescription(_description); + } +} + +template +esignal::Signal::Signal(esignal::Interface* _signalInterfaceLink, + const std::string& _name, + const std::string& _description): + m_signalInterfaceLink(_signalInterfaceLink) { + // create internal data assiciated: + m_data = ememory::makeShared>(nullptr); + if (esignal::Base::m_data != nullptr) { + esignal::Base::m_data->setName(_name); + esignal::Base::m_data->setDescription(_description); + } + // add a reference on the current signal ... + if (m_signalInterfaceLink != nullptr) { + m_signalInterfaceLink->signals.add(this); + } +} + +template +void esignal::SignalInternal::emit(const T_ARGS&... _args) { #ifdef DEBUG int32_t tmpID = s_uidSignalEmit++; #endif @@ -56,7 +87,7 @@ void esignal::Signal::emit(const T_ARGS&... _args) { } template -void esignal::Signal::removeIfPossible() { +void esignal::SignalInternal::removeIfPossible() { if (m_callInProgress != 0) { return; } @@ -79,7 +110,7 @@ void esignal::Signal::removeIfPossible() { } template -void esignal::Signal::disconnect(size_t _uid) { +void esignal::SignalInternal::disconnect(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; @@ -90,7 +121,7 @@ void esignal::Signal::disconnect(size_t _uid) { } template -void esignal::Signal::disconnectShared(const ememory::SharedPtr& _obj) { +void esignal::SignalInternal::disconnectShared(const ememory::SharedPtr& _obj) { for (size_t iii=0; iii < m_executors.size(); ++iii) { if (m_executors[iii]->isSharedPtr(_obj) == true) { m_executors[iii]->m_removed = true; @@ -100,17 +131,17 @@ void esignal::Signal::disconnectShared(const ememory::SharedPtr } template -size_t esignal::Signal::size() const { +size_t esignal::SignalInternal::size() const { return m_executors.size(); } template -bool esignal::Signal::empty() const { +bool esignal::SignalInternal::empty() const { return m_executors.empty(); } template -void esignal::Signal::clear() { +void esignal::SignalInternal::clear() { for (size_t iii=0; iii < m_executors.size(); ++iii) { m_executors[iii]->m_removed = true; } @@ -119,7 +150,7 @@ void esignal::Signal::clear() { template -esignal::Signal::Executor::Executor(Observer&& _observer): +esignal::SignalInternal::Executor::Executor(Observer&& _observer): m_removed(false), m_uid(0) { m_uid = s_uid++; @@ -127,7 +158,7 @@ esignal::Signal::Executor::Executor(Observer&& _observer): } template -void esignal::Signal::Executor::emit(const T_ARGS&... _values) { +void esignal::SignalInternal::Executor::emit(const T_ARGS&... _values) { if (m_removed == true) { return; } @@ -139,7 +170,7 @@ void esignal::Signal::Executor::emit(const T_ARGS&... _values) { } template -bool esignal::Signal::Executor::isSharedPtr(const ememory::SharedPtr& _obj) { +bool esignal::SignalInternal::Executor::isSharedPtr(const ememory::SharedPtr& _obj) { return false; } @@ -147,14 +178,14 @@ bool esignal::Signal::Executor::isSharedPtr(const ememory::SharedPtr< template -esignal::Signal::ExecutorShared::ExecutorShared(ememory::WeakPtr _object, Observer&& _observer) : +esignal::SignalInternal::ExecutorShared::ExecutorShared(ememory::WeakPtr _object, Observer&& _observer) : Executor(std::move(_observer)), m_object(_object) { } template -void esignal::Signal::ExecutorShared::emit(const T_ARGS&... _values) { +void esignal::SignalInternal::ExecutorShared::emit(const T_ARGS&... _values) { // TODO: maybe an error if the object is not manage by the same thread. ememory::SharedPtr destObject = m_object.lock(); if (destObject == nullptr) { @@ -172,7 +203,7 @@ void esignal::Signal::ExecutorShared::emit(const T_ARGS&... _values) } template -bool esignal::Signal::ExecutorShared::isSharedPtr(const ememory::SharedPtr& _obj) { +bool esignal::SignalInternal::ExecutorShared::isSharedPtr(const ememory::SharedPtr& _obj) { ememory::SharedPtr destObject = m_object.lock(); if (destObject == nullptr) { return true; diff --git a/lutin_esignal.py b/lutin_esignal.py index 8ca95a4..6accf50 100644 --- a/lutin_esignal.py +++ b/lutin_esignal.py @@ -35,10 +35,7 @@ def create(target, module_name): 'esignal/Connection.cpp', 'esignal/InterfaceData.cpp', 'esignal/Base.cpp', - 'esignal/details/LockSharedPtrRef.cpp', - 'esignal/details/RefCount.cpp', 'esignal/details/Signal.cpp', - 'esignal/details/ISignal.cpp', ]) my_module.add_header_file([ 'esignal/debug.h', @@ -46,14 +43,8 @@ def create(target, module_name): 'esignal/InterfaceData.h', 'esignal/Base.h', 'esignal/Signal.h', - 'esignal/ISignal.h', - 'esignal/LockSharedPtrRef.h', - 'esignal/RefCount.h', 'esignal/Connection.h', 'esignal/details/Signal.hxx', - 'esignal/details/ISignal.hxx', - 'esignal/details/LockSharedPtrRef.hxx', - 'esignal/details/RefCount.hxx', ]) my_module.compile_version("c++", 2011) my_module.add_module_depend([ diff --git a/sample/sampleAll.cpp b/sample/sampleAll.cpp index 7594b85..7dd87a8 100644 --- a/sample/sampleAll.cpp +++ b/sample/sampleAll.cpp @@ -132,7 +132,7 @@ void newSignal() { // do it in a single C++: Implementation of signal //! [esignal_sample_new_register] #include -template class esignal::Signal; +ESIGNAL_DECLARE_SIGNAL(int32_t, std::string); //! [esignal_sample_new_register] //! [esignal_sample_new] diff --git a/test/declareSignals.cpp b/test/declareSignals.cpp index 1d721d9..9b712d0 100644 --- a/test/declareSignals.cpp +++ b/test/declareSignals.cpp @@ -8,6 +8,7 @@ #include #include -template class esignal::Signal; + +ESIGNAL_DECLARE_SIGNAL(int32_t, std::string); diff --git a/test/test_isignal.cpp b/test/test_isignal.cpp index 6cd4c25..f60c5e4 100644 --- a/test/test_isignal.cpp +++ b/test/test_isignal.cpp @@ -8,7 +8,7 @@ #define NAME "SingleArg" #include -#include +#include #include #include #include @@ -16,9 +16,9 @@ class testISignal : public esignal::Interface { public: - esignal::ISignal m_signalInt; - esignal::ISignal m_signalString; - esignal::ISignal m_signalFloat; + esignal::Signal m_signalInt; + esignal::Signal m_signalString; + esignal::Signal m_signalFloat; public: size_t m_count; testISignal():