diff --git a/esignal/Base.h b/esignal/Base.h index 2b9877a..60fbd5e 100644 --- a/esignal/Base.h +++ b/esignal/Base.h @@ -20,7 +20,7 @@ namespace esignal { class Base { protected: - LockSharedPtrRef m_shared; //!< Reference counter on itself. + esignal::LockSharedPtrRef m_shared; //!< Reference counter on itself. static size_t s_uid; //!< blobal id of the signal (STATIC) public: //! @brief Basic constructor: diff --git a/esignal/Connection.cpp b/esignal/Connection.cpp new file mode 100644 index 0000000..6a3e2c6 --- /dev/null +++ b/esignal/Connection.cpp @@ -0,0 +1,48 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2016, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ +#include +#include + +esignal::Connection::Connection(): + m_signalRefUnique(), m_uid(0) { + +} + +esignal::Connection::Connection(const esignal::LockSharedPtrRef& _ref, std::size_t _id): + m_signalRefUnique(_ref), + m_uid(_id) { + +} + +esignal::Connection::Connection(esignal::Connection&& _obj): + m_signalRefUnique(_obj.m_signalRefUnique), + m_uid(_obj.m_uid) { + _obj.m_uid = 0; +} + +esignal::Connection& esignal::Connection::operator=(esignal::Connection&& _obj) { + disconnect(); + m_signalRefUnique = _obj.m_signalRefUnique; + m_uid = _obj.m_uid; + _obj.m_uid = 0; + return *this; +} +esignal::Connection::~Connection() { + m_signalRefUnique.disconnect(m_uid); + m_uid = 0; +} + +void esignal::Connection::disconnect() { + m_signalRefUnique.disconnect(m_uid); + m_uid = 0; +} + +bool esignal::Connection::isConnected() { + return m_signalRefUnique.isAlive(); +} + diff --git a/esignal/Connection.h b/esignal/Connection.h index 6cf743e..61b70d2 100644 --- a/esignal/Connection.h +++ b/esignal/Connection.h @@ -23,54 +23,29 @@ namespace esignal { class Connection { public: //! @brief Constructor (no link) - Connection(): - m_signalRefUnique(), m_uid(0) { - - } + Connection(); //! @brief Constructor (link) - Connection(const LockSharedPtrRef& _ref, std::size_t _id): - m_signalRefUnique(_ref), - m_uid(_id) { - - } + Connection(const esignal::LockSharedPtrRef& _ref, std::size_t _id); //! @brief Move Constructor - Connection(Connection&& _obj): - m_signalRefUnique(_obj.m_signalRefUnique), - m_uid(_obj.m_uid) { - _obj.m_uid = 0; - } + Connection(Connection&& _obj); //! @brief Move operator. - Connection& operator=(Connection&& _obj) { - disconnect(); - m_signalRefUnique = _obj.m_signalRefUnique; - m_uid = _obj.m_uid; - _obj.m_uid = 0; - return *this; - } + Connection& operator=(Connection&& _obj); //! @brief Copy constructor (REMOVED) Connection(const Connection&) = delete; //! @brief Copy operator (REMOVED) Connection& operator=(const Connection&) = delete; //! @brief Destructor. - ~Connection() { - m_signalRefUnique.disconnect(m_uid); - m_uid = 0; - } + ~Connection(); //! @brief Disconnect the signal. - void disconnect() { - m_signalRefUnique.disconnect(m_uid); - m_uid = 0; - } + void disconnect(); /** * @brief Check if the connection is alive or signal removed * @return true The signal is connected. * @return false The signal is NOT connected. */ - bool isConnected() { - return m_signalRefUnique.isAlive(); - } + bool isConnected(); private: - LockSharedPtrRef m_signalRefUnique; //!< reference on the Signal. + esignal::LockSharedPtrRef m_signalRefUnique; //!< reference on the Signal. std::size_t m_uid; //!< UID of the current connection. }; } diff --git a/esignal/ISignal.h b/esignal/ISignal.h index 00d86e7..5d200df 100644 --- a/esignal/ISignal.h +++ b/esignal/ISignal.h @@ -33,25 +33,13 @@ namespace esignal { */ 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 ... - m_signalInterfaceLink.signalAdd(this); - } + const std::string& _description = ""); /** * @brief Destructor. */ - virtual ~ISignal() { - m_signalInterfaceLink.signalRemove(this); - } - virtual const std::string& getName() const { - return m_name; - } - virtual const std::string& getDescription() const { - return m_description; - } + virtual ~ISignal(); + virtual const std::string& getName() const; + virtual const std::string& getDescription() const; }; } diff --git a/esignal/LockSharedPtrRef.h b/esignal/LockSharedPtrRef.h index f3dc5c2..a3e5f16 100644 --- a/esignal/LockSharedPtrRef.h +++ b/esignal/LockSharedPtrRef.h @@ -7,18 +7,9 @@ */ #pragma once -#include -#include -#include -#include #include -#include -#include -#include -#include namespace esignal { - extern size_t s_uid; /** * @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. @@ -27,58 +18,29 @@ namespace esignal { template class LockSharedPtrRef { public: - RefCount* m_counter; //!< Access on the reference counter + 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) : - m_counter(nullptr) { - if (_pointer != nullptr) { - m_counter = new RefCount(_pointer); - m_counter->inc(); - } - } + LockSharedPtrRef(TYPE* _pointer=nullptr); /** * @brief Copy contructor * @param[in] _obj object to copy */ - LockSharedPtrRef(const LockSharedPtrRef& _obj) : - m_counter(_obj.m_counter) { - if (m_counter == nullptr) { - return; - } - m_counter->inc(); - } + LockSharedPtrRef(const LockSharedPtrRef& _obj); /** * @brief Copy operator (It copy the counter and increment the it). * @param[in] _obj objetc to copy. * @return Reference of this */ - LockSharedPtrRef& operator=(const LockSharedPtrRef& _obj) { - if (&_obj == this) { - return *this; - } - if (m_counter != nullptr) { - m_counter->dec(); - m_counter = nullptr; - } - m_counter = _obj.m_counter; - if (m_counter == nullptr) { - return *this; - } - m_counter->inc(); - return *this; - } + LockSharedPtrRef& operator=(const LockSharedPtrRef& _obj); /** * @brief Contructor (move) * @param[in] _obj move object */ - LockSharedPtrRef(LockSharedPtrRef&& _obj) : - m_counter(std::move(_obj.m_counter)) { - - } + LockSharedPtrRef(LockSharedPtrRef&& _obj); /** * @brief Copy operator (force move) ==> removed */ @@ -86,48 +48,22 @@ namespace esignal { /** * @brief Destructor of the class (decrement the counter and remove it if it is the last one...) */ - ~LockSharedPtrRef() { - if (m_counter == nullptr) { - return; - } - int64_t count = m_counter->dec(); - if (count > 0) { - return; - } - delete m_counter; - m_counter = nullptr; - } + ~LockSharedPtrRef(); /** * @brief Remove the data on the conter reference (it does not exist anymore) */ - void removeData() { - if (m_counter != nullptr) { - m_counter->remove(); - } - } + void removeData(); /** * @brief Call disconnect on the parameter class with lock prevention * @param[in] _uid ID to dicsonnect on the sub element */ - void disconnect(std::size_t _uid) { - if (m_counter == nullptr) { - return; - } - m_counter->lock(); - TYPE* val = m_counter->get(); - if (val != nullptr) { - val->disconnect(_uid); - } - m_counter->unlock(); - } + void disconnect(std::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() { - return m_counter != nullptr; - } + bool isAlive(); }; } diff --git a/esignal/RefCount.h b/esignal/RefCount.h index fe4b86b..250388f 100644 --- a/esignal/RefCount.h +++ b/esignal/RefCount.h @@ -7,10 +7,6 @@ */ #pragma once -#include -#include -#include -#include #include #include @@ -26,11 +22,7 @@ namespace esignal { TYPE* m_data; //!< Pointer on the refconting data public: //!< generic constructor - RefCount(TYPE* _data) : - m_count(0), - m_data(_data) { - // nothing to do. - } + RefCount(TYPE* _data); //! @brief Copy constructor (REMOVED) RefCount(const RefCount&) = delete; //! @brief Copy operator (REMOVED) @@ -42,46 +34,21 @@ namespace esignal { //! @brief Move operator (REMOVED) RefCount& operator=(RefCount&& _obj) = delete; //! @brief Destructor - ~RefCount() { - m_data = nullptr; - } + ~RefCount(); public: //!< @brief Lock the interface - void lock() { - m_lock.lock(); - } + void lock(); //!< @brief Unlock the interface - void unlock() { - m_lock.unlock(); - } + void unlock(); //!< @brief Increment the ref-counting - void inc() { - lock(); - m_count++; - unlock(); - } + void inc(); //!< @brief Decrement the ref-counting - int64_t dec() { - int64_t val; - lock(); - m_count--; - val = m_count; - unlock(); - return val; - } + int64_t dec(); //!< @brief Get number of connected - int64_t getCount() const { - return m_count; - } + int64_t getCount() const; //!< @brief Remove the data - void remove() { - lock(); - m_data = nullptr; - unlock(); - } + void remove(); //!< @brief Get the recoreded data - TYPE* get() { - return m_data; - } + TYPE* get(); }; } diff --git a/esignal/Signal.h b/esignal/Signal.h index 7d704c5..ea4b51e 100644 --- a/esignal/Signal.h +++ b/esignal/Signal.h @@ -66,6 +66,12 @@ namespace esignal { */ virtual void emit(const T_ARGS&... _values); public: + /** + * @brief check if the Executor is a managed by this shared_ptr + * @param[in] _obj Object to check + * @return true The Executor depend on this shared_ptr + * @return false The Executor does not depend on this shared_ptr + */ virtual bool isSharedPtr(const std::shared_ptr& _obj); }; protected: @@ -99,48 +105,28 @@ namespace esignal { * @brief Connect an observer on the signal. * @param[in] _observer Observer to call. */ - template< class ObserverType > - Connection connect(ObserverType&& _observer ) { - std::unique_ptr executer(new Executor(std::forward(_observer))); - std::size_t uid = executer->m_uid; - m_executors.push_back(std::move(executer)); - return Connection(Base::m_shared, uid); - } + template< class OBSERVER_TYPE > + esignal::Connection connect(OBSERVER_TYPE&& _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] _arg Argument optinnal the user want to add. */ - template - Connection connect(classType* _class, Func _func, Arg... _arg) { - std::unique_ptr executer(new Executor([=](const T_ARGS& ... _argBase){ - (*_class.*_func)(_argBase..., _arg... ); - })); - std::size_t uid = executer->m_uid; - m_executors.push_back(std::move(executer)); - return Connection(Base::m_shared, uid); - } + template + esignal::Connection connect(CLASS_TYPE* _class, + FUNC_TYPE _func, + FUNC_ARGS_TYPE... _arg); /** * @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] _arg Argument optinnal the user want to add. */ - template - 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 T_ARGS& ... _argBase){ - // TODO : Check if compilator does not use the shared ptr ... - (*directPointer.*_func)(_argBase..., _args... ); - })); - m_executors.push_back(std::move(executer)); - } + template + void connect(const std::shared_ptr& _class, + void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), + FUNC_ARGS_TYPE... _args); public: /** * @brief Emit data on the signal. @@ -175,3 +161,42 @@ namespace esignal { } +template +template< class OBSERVER_TYPE > +esignal::Connection esignal::Signal::connect(OBSERVER_TYPE&& _observer ) { + std::unique_ptr executer(new Executor(std::forward(_observer))); + std::size_t uid = executer->m_uid; + m_executors.push_back(std::move(executer)); + return Connection(Base::m_shared, uid); +} + +template +template +esignal::Connection esignal::Signal::connect(CLASS_TYPE* _class, + FUNC_TYPE _func, + FUNC_ARGS_TYPE... _arg) { + std::unique_ptr executer(new Executor([=](const T_ARGS& ... _argBase){ + (*_class.*_func)(_argBase..., _arg... ); + })); + std::size_t uid = executer->m_uid; + m_executors.push_back(std::move(executer)); + return Connection(Base::m_shared, uid); +} + +template +template +void esignal::Signal::connect(const std::shared_ptr& _class, + void (CLASS_TYPE::*_func)(const T_ARGS&..., FUNC_ARGS_TYPE...), + FUNC_ARGS_TYPE... _args) { + std::shared_ptr obj2 = std::dynamic_pointer_cast(_class); + if (obj2 == nullptr) { + ESIGNAL_ERROR("Can not bind signal ..."); + return; + } + CLASS_TYPE* directPointer = obj2.get(); + 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... ); + })); + m_executors.push_back(std::move(executer)); +} \ No newline at end of file diff --git a/esignal/details/ISignal.cpp b/esignal/details/ISignal.cpp new file mode 100644 index 0000000..e99a4c5 --- /dev/null +++ b/esignal/details/ISignal.cpp @@ -0,0 +1,51 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2016, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ +#include +#include +#include +#include +#include + +#undef __class__ +#define __class__ "ISignal" +// 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 new file mode 100644 index 0000000..2e85d66 --- /dev/null +++ b/esignal/details/ISignal.hxx @@ -0,0 +1,39 @@ +/** + * @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 ... + m_signalInterfaceLink.signalAdd(this); +} + +template +esignal::ISignal::~ISignal() { + m_signalInterfaceLink.signalRemove(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 new file mode 100644 index 0000000..b4239ac --- /dev/null +++ b/esignal/details/LockSharedPtrRef.cpp @@ -0,0 +1,16 @@ +/** + * @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 new file mode 100644 index 0000000..186bfbc --- /dev/null +++ b/esignal/details/LockSharedPtrRef.hxx @@ -0,0 +1,91 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2016, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include + +template +esignal::LockSharedPtrRef::LockSharedPtrRef(TYPE* _pointer) : + m_counter(nullptr) { + if (_pointer != nullptr) { + m_counter = new RefCount(_pointer); + m_counter->inc(); + } +} + +template +esignal::LockSharedPtrRef::LockSharedPtrRef(const LockSharedPtrRef& _obj) : + m_counter(_obj.m_counter) { + if (m_counter == nullptr) { + return; + } + m_counter->inc(); +} + +template +esignal::LockSharedPtrRef& esignal::LockSharedPtrRef::operator=(const esignal::LockSharedPtrRef& _obj) { + if (&_obj == this) { + return *this; + } + if (m_counter != nullptr) { + m_counter->dec(); + m_counter = nullptr; + } + m_counter = _obj.m_counter; + if (m_counter == nullptr) { + return *this; + } + m_counter->inc(); + return *this; +} + +template +esignal::LockSharedPtrRef::LockSharedPtrRef(LockSharedPtrRef&& _obj) : + m_counter(std::move(_obj.m_counter)) { + +} + +template +esignal::LockSharedPtrRef::~LockSharedPtrRef() { + if (m_counter == nullptr) { + return; + } + int64_t count = m_counter->dec(); + if (count > 0) { + return; + } + delete m_counter; + m_counter = nullptr; +} + +template +void esignal::LockSharedPtrRef::removeData() { + if (m_counter != nullptr) { + m_counter->remove(); + } +} + +template +void esignal::LockSharedPtrRef::disconnect(std::size_t _uid) { + if (m_counter == nullptr) { + return; + } + m_counter->lock(); + TYPE* val = m_counter->get(); + if (val != nullptr) { + val->disconnect(_uid); + } + m_counter->unlock(); +} + +template +bool esignal::LockSharedPtrRef::isAlive() { + return m_counter != nullptr; +} + + + diff --git a/esignal/details/RefCount.cpp b/esignal/details/RefCount.cpp new file mode 100644 index 0000000..d9d2b97 --- /dev/null +++ b/esignal/details/RefCount.cpp @@ -0,0 +1,16 @@ +/** + * @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 new file mode 100644 index 0000000..e3f970e --- /dev/null +++ b/esignal/details/RefCount.hxx @@ -0,0 +1,66 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2016, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include + +template +esignal::RefCount::RefCount(TYPE* _data) : + m_count(0), + m_data(_data) { + // nothing to do. +} + +template +esignal::RefCount::~RefCount() { + m_data = nullptr; +} + +template +void esignal::RefCount::lock() { + m_lock.lock(); +} + +template +void esignal::RefCount::unlock() { + m_lock.unlock(); +} + +template +void esignal::RefCount::inc() { + lock(); + m_count++; + unlock(); +} + +template +int64_t esignal::RefCount::dec() { + int64_t val; + lock(); + m_count--; + val = m_count; + unlock(); + return val; +} + +template +int64_t esignal::RefCount::getCount() const { + return m_count; +} + +template +void esignal::RefCount::remove() { + lock(); + m_data = nullptr; + unlock(); +} + +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 abc319f..f0536c8 100644 --- a/esignal/details/Signal.cpp +++ b/esignal/details/Signal.cpp @@ -11,8 +11,6 @@ #include #include -size_t esignal::s_uid = 0; - #undef __class__ #define __class__ "Signal" // void generic signal diff --git a/esignal/details/Signal.hxx b/esignal/details/Signal.hxx index 182fdbf..8fd7ca4 100644 --- a/esignal/details/Signal.hxx +++ b/esignal/details/Signal.hxx @@ -8,13 +8,10 @@ #pragma once #include -#include -#include #undef __class__ #define __class__ "Signal" - template esignal::Signal::Signal(): m_callInProgress(0) { diff --git a/lutin_esignal.py b/lutin_esignal.py index e0c8e85..ebdc80f 100644 --- a/lutin_esignal.py +++ b/lutin_esignal.py @@ -32,9 +32,13 @@ def create(target, module_name): my_module.add_extra_compile_flags() my_module.add_src_file([ 'esignal/debug.cpp', + 'esignal/Connection.cpp', 'esignal/Interface.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,6 +50,9 @@ def create(target, module_name): '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(['etk']) diff --git a/test/declareSignals.cpp b/test/declareSignals.cpp new file mode 100644 index 0000000..1d721d9 --- /dev/null +++ b/test/declareSignals.cpp @@ -0,0 +1,13 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2016, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ +#include +#include + +template class esignal::Signal; + +