diff --git a/doc/mainpage.md b/doc/mainpage.md new file mode 100644 index 0000000..a08450e --- /dev/null +++ b/doc/mainpage.md @@ -0,0 +1,43 @@ +ESIGNAL library {#mainpage} +=============== + +What is ESIGNAL, and how can I use it? +---------------------------------- + +ESIGNAL, or Ewol signal engine is a simple messaging layer, managing multiple connection and manage disconnection + +ESIGNAL is designed for + - Expose signal + - Emit synchronous signal (not send through an event loop but directly) + - Manage versatil connection/disconnection + + +What languages are supported? +----------------------------- + +ESIGNAL is written in C++. + + +Are there any licensing restrictions? +------------------------------------- + +ESIGNAL is **FREE software** and _all sub-library are FREE and staticly linkable !!!_ + + +License (APACHE-2.0) +-------------------- + +Copyright esignal Edouard DUPIN + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/doxy_esignal.py b/doxy_esignal.py index 39614ad..f43ddb8 100644 --- a/doxy_esignal.py +++ b/doxy_esignal.py @@ -10,9 +10,13 @@ def create(target, module_name): my_module.set_title("esignal: Ewol signal interface") my_module.set_website("http://atria-soft.github.io/" + module_name) my_module.set_website_sources("http://github.com/atria-soft/" + module_name) - my_module.set_path(os.path.join(tools.get_current_path(__file__), module_name)) + my_module.add_path([ + module_name, + "doc" + ]) my_module.add_module_depend([ - 'etk' + 'etk', + 'ememory' ]) return my_module \ No newline at end of file diff --git a/esignal/Base.h b/esignal/Base.h index 7945ade..381a11e 100644 --- a/esignal/Base.h +++ b/esignal/Base.h @@ -18,6 +18,9 @@ #include namespace esignal { + /** + * @brief Base signal interface for esignal::Signal (permit to create abstract list of signals...) + */ class Base { public: using ObserverConnection = std::function; //!< Define an Observer of the number of observer @@ -25,7 +28,7 @@ namespace esignal { 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; + ObserverConnection m_connectionObserver; //!< propriétéry of the connection handle basic public: //! @brief Basic constructor: Base(ObserverConnection _countObs = nullptr); @@ -36,10 +39,15 @@ namespace esignal { virtual ~Base(); /** - * @brief get name of the signal + * @brief Disconnect the shared_ptr form the Signal + * @param[in] _obj Link with the object to check */ virtual void disconnectShared(const std::shared_ptr& _obj) = 0; - virtual void disconnect(std::size_t _uid) = 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. @@ -51,6 +59,7 @@ namespace esignal { */ virtual const std::string& getDescription() const; }; + //! @not_in_doc std::ostream& operator <<(std::ostream& _os, const esignal::Base& _obj); #ifdef DEBUG const char* logIndent(int32_t _iii); diff --git a/esignal/Connection.cpp b/esignal/Connection.cpp index 6a3e2c6..68ec62a 100644 --- a/esignal/Connection.cpp +++ b/esignal/Connection.cpp @@ -13,7 +13,7 @@ esignal::Connection::Connection(): } -esignal::Connection::Connection(const esignal::LockSharedPtrRef& _ref, std::size_t _id): +esignal::Connection::Connection(const esignal::LockSharedPtrRef& _ref, size_t _id): m_signalRefUnique(_ref), m_uid(_id) { diff --git a/esignal/Connection.h b/esignal/Connection.h index 61b70d2..15d318e 100644 --- a/esignal/Connection.h +++ b/esignal/Connection.h @@ -25,7 +25,7 @@ namespace esignal { //! @brief Constructor (no link) Connection(); //! @brief Constructor (link) - Connection(const esignal::LockSharedPtrRef& _ref, std::size_t _id); + Connection(const esignal::LockSharedPtrRef& _ref, size_t _id); //! @brief Move Constructor Connection(Connection&& _obj); //! @brief Move operator. @@ -46,7 +46,7 @@ namespace esignal { bool isConnected(); private: esignal::LockSharedPtrRef m_signalRefUnique; //!< reference on the Signal. - std::size_t m_uid; //!< UID of the current connection. + size_t m_uid; //!< UID of the current connection. }; } diff --git a/esignal/ISignal.h b/esignal/ISignal.h index 7a6c236..fe2a4bc 100644 --- a/esignal/ISignal.h +++ b/esignal/ISignal.h @@ -31,7 +31,7 @@ namespace esignal { /** * @brief Create a signal with a specific type. * @param[in] _signalInterfaceLink reference on the signal lister. - * @param[in] _countObs (optionnal) Local observer to know the count of connection on the signal. + * @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. */ @@ -40,6 +40,12 @@ namespace esignal { 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); @@ -47,8 +53,8 @@ namespace esignal { * @brief Destructor. */ virtual ~ISignal(); - virtual const std::string& getName() const; - virtual const std::string& getDescription() const; + const std::string& getName() const override; + const std::string& getDescription() const override; }; } @@ -64,7 +70,7 @@ esignal::ISignal::ISignal(CLASS_TYPE* _class, m_description(_description) { // add a reference on the current signal ... if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signalAdd(this); + m_signalInterfaceLink->signal.add(this); } } diff --git a/esignal/Interface.cpp b/esignal/Interface.cpp index 80e30e5..68e0377 100644 --- a/esignal/Interface.cpp +++ b/esignal/Interface.cpp @@ -11,16 +11,16 @@ #include #include -esignal::Interface::Interface() { +esignal::InterfaceData::InterfaceData() { } -esignal::Interface::~Interface() { +esignal::InterfaceData::~InterfaceData() { m_list.clear(); } // note this pointer is not allocated and not free at the end of the class -void esignal::Interface::signalAdd(esignal::Base* _pointerOnSignal) { +void esignal::InterfaceData::add(esignal::Base* _pointerOnSignal) { if (_pointerOnSignal == nullptr) { ESIGNAL_ERROR("Try to link a nullptr parameters"); return; @@ -28,7 +28,7 @@ void esignal::Interface::signalAdd(esignal::Base* _pointerOnSignal) { m_list.push_back(_pointerOnSignal); } -void esignal::Interface::signalRemove(esignal::Base* _pointerOnSignal) { +void esignal::InterfaceData::remove(esignal::Base* _pointerOnSignal) { auto it = m_list.begin(); while (it != m_list.end()) { if ( *it == nullptr @@ -40,7 +40,7 @@ void esignal::Interface::signalRemove(esignal::Base* _pointerOnSignal) { } } -std::vector esignal::Interface::signalGetAll() const { +std::vector esignal::InterfaceData::getAll() const { std::vector out; for (auto &it : m_list) { if(it != nullptr) { @@ -50,7 +50,7 @@ std::vector esignal::Interface::signalGetAll() const { return out; } -void esignal::Interface::signalDisconnect(const std::shared_ptr& _object) { +void esignal::InterfaceData::disconnect(const std::shared_ptr& _object) { if (_object == nullptr) { ESIGNAL_ERROR("Input ERROR nullptr pointer Object ..."); return; @@ -62,3 +62,5 @@ void esignal::Interface::signalDisconnect(const std::shared_ptr& _object) it->disconnectShared(_object); } } + + diff --git a/esignal/Interface.h b/esignal/Interface.h index bbe9e83..99b2d50 100644 --- a/esignal/Interface.h +++ b/esignal/Interface.h @@ -12,36 +12,51 @@ namespace esignal { class Base; - class Interface { - friend class esignal::Base; // to register parameter in the list. + /** + * @brief Interface data to collect the Signal list (for abstarction connection) + */ + class InterfaceData { private: std::vector m_list; //!< list of availlable Parameters public: /** * @brief Constructor. */ - Interface(); + InterfaceData(); /** * @brief Destructor. */ - virtual ~Interface(); + virtual ~InterfaceData(); /** - * @brief Register a parameter class pointer in the List of parameters + * @brief Register a signal class pointer in the List of signal list * @note This class does not destroy the parameter pointer!!! * @param[in] _pointerOnSignal Pointer on the signal that might be added. */ - void signalAdd(esignal::Base* _pointerOnSignal); - void signalRemove(esignal::Base* _pointerOnSignal); + void add(esignal::Base* _pointerOnSignal); + /** + * @brief Remove a signal class pointer in the List of signal list + * @note This class does not destroy the parameter pointer!!! + * @param[in] _pointerOnSignal Pointer on the signal that might be removed. + */ + void remove(esignal::Base* _pointerOnSignal); /** * @brief Get All the signal list: * @return vector on all the signals names */ - std::vector signalGetAll() const; + std::vector getAll() const; /** * @brief Remove binding on all event class. * @param[in] _sharedPtr sharedPtr to unlink (no type needed ...). */ - void signalDisconnect(const std::shared_ptr& _sharedPtr); + void disconnect(const std::shared_ptr& _sharedPtr); + }; + /** + * @brief Interface to collect the Signal list (for abstarction connection) + * It create a simple "signal" member that permit to access at the signalproperties. + */ + class Interface { + public: + esignal::InterfaceData signal; //!< Interface to access at all signal properties... }; } diff --git a/esignal/LockSharedPtrRef.h b/esignal/LockSharedPtrRef.h index d3ef1d5..726d037 100644 --- a/esignal/LockSharedPtrRef.h +++ b/esignal/LockSharedPtrRef.h @@ -13,7 +13,7 @@ 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. - * @input[in] TYPE Type of the internal data + * @param TYPE Type of the internal data */ template class LockSharedPtrRef { @@ -60,7 +60,7 @@ namespace esignal { * @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); + void disconnect(size_t _uid); /** * @brief Check if the value is availlable * @return true The data is availlable diff --git a/esignal/RefCount.h b/esignal/RefCount.h index 250388f..1ed5f68 100644 --- a/esignal/RefCount.h +++ b/esignal/RefCount.h @@ -21,7 +21,10 @@ namespace esignal { int64_t m_count; //!< number of element connected TYPE* m_data; //!< Pointer on the refconting data public: - //!< generic constructor + /** + * @brief generic constructor + * @param[in] _data Data to reference the Refcounting + */ RefCount(TYPE* _data); //! @brief Copy constructor (REMOVED) RefCount(const RefCount&) = delete; @@ -36,19 +39,19 @@ namespace esignal { //! @brief Destructor ~RefCount(); public: - //!< @brief Lock the interface + //! @brief Lock the interface void lock(); - //!< @brief Unlock the interface + //! @brief Unlock the interface void unlock(); - //!< @brief Increment the ref-counting + //! @brief Increment the ref-counting void inc(); - //!< @brief Decrement the ref-counting + //! @brief Decrement the ref-counting int64_t dec(); - //!< @brief Get number of connected + //! @brief Get number of connected int64_t getCount() const; - //!< @brief Remove the data + //! @brief Remove the data void remove(); - //!< @brief Get the recoreded data + //! @brief Get the recoreded data TYPE* get(); }; } diff --git a/esignal/Signal.h b/esignal/Signal.h index 731c696..eee6c0d 100644 --- a/esignal/Signal.h +++ b/esignal/Signal.h @@ -35,10 +35,15 @@ namespace esignal { int32_t m_callInProgress; //!< know if we are in a recursive loop public: /** - * @brief Basic constructor + * @brief Basic constructor with connection observer * @param[in] _countObs Local observer to know the count of connection on the signal. */ 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) @@ -87,7 +92,6 @@ namespace esignal { private: /** * @brief Executor specific to the Shared_ptr caller that does not want to worry about the removing of the signal. - * @param[in] T_ARGS... Argument of the signal */ class ExecutorShared : public Executor { protected: @@ -106,12 +110,13 @@ namespace esignal { */ virtual void emit(const T_ARGS&... _values); public: - virtual bool isSharedPtr(const std::shared_ptr& _obj); + bool isSharedPtr(const std::shared_ptr& _obj) override; }; 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); @@ -120,6 +125,7 @@ namespace esignal { * @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. + * @return Connection handle (connection is removed if the handle is destroy) */ template esignal::Connection connect(CLASS_TYPE* _class, @@ -129,7 +135,7 @@ namespace esignal { * @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. + * @param[in] _args Argument optinnal the user want to add. */ template void connect(const std::shared_ptr& _class, @@ -142,14 +148,22 @@ namespace esignal { */ void emit(const T_ARGS&... _args); protected: + /** + * @brief Remove observer in the internal list if the user has disconnected + * @note Done only if it is the last caller ... + */ void removeIfPossible(); public: /** * @brief Disconnect an observer of the signal. - * @param[in] _uid Unique id of the signal. + * @param[in] _uid Unique id of the signal connection. */ - void disconnect(std::size_t _uid); - void disconnectShared(const std::shared_ptr& _obj); + void disconnect(size_t _uid) override; + /** + * @brief Disconnect the shared_ptr form the Signal + * @param[in] _obj Link with the object to check + */ + void disconnectShared(const std::shared_ptr& _obj) override; /** * @brief Get the number of observers connected on the signal. * @return The count of observer. @@ -174,7 +188,7 @@ template< class OBSERVER_TYPE > esignal::Connection esignal::Signal::connect(OBSERVER_TYPE&& _observer ) { ESIGNAL_DEBUG("esignal: '" << getName() << "' try connect: '" << getName() << "' (observer)"); std::unique_ptr executer(new Executor(std::forward(_observer))); - std::size_t uid = executer->m_uid; + size_t uid = executer->m_uid; m_executors.push_back(std::move(executer)); if (m_connectionObserver!=nullptr) { m_connectionObserver(m_executors.size()); @@ -196,7 +210,7 @@ esignal::Connection esignal::Signal::connect(CLASS_TYPE* _class, std::unique_ptr executer(new Executor([=](const T_ARGS& ... _argBase){ (*_class.*_func)(_argBase..., _arg... ); })); - std::size_t uid = executer->m_uid; + size_t uid = executer->m_uid; m_executors.push_back(std::move(executer)); if (m_connectionObserver != nullptr) { m_connectionObserver(m_executors.size()); diff --git a/esignal/details/ISignal.hxx b/esignal/details/ISignal.hxx index eed5d22..b9cd2de 100644 --- a/esignal/details/ISignal.hxx +++ b/esignal/details/ISignal.hxx @@ -10,9 +10,6 @@ #include #include -#undef __class__ -#define __class__ "ISignal" - template esignal::ISignal::ISignal(esignal::Interface* _signalInterfaceLink, const std::string& _name, @@ -22,14 +19,14 @@ esignal::ISignal::ISignal(esignal::Interface* _signalInterfaceLink, m_description(_description) { // add a reference on the current signal ... if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signalAdd(this); + m_signalInterfaceLink->signal.add(this); } } template esignal::ISignal::~ISignal() { if (m_signalInterfaceLink != nullptr) { - m_signalInterfaceLink->signalRemove(this); + m_signalInterfaceLink->signal.remove(this); } } @@ -43,6 +40,3 @@ const std::string& esignal::ISignal::getDescription() const { return m_description; } -#undef __class__ -#define __class__ nullptr - diff --git a/esignal/details/LockSharedPtrRef.hxx b/esignal/details/LockSharedPtrRef.hxx index 40eddeb..832987d 100644 --- a/esignal/details/LockSharedPtrRef.hxx +++ b/esignal/details/LockSharedPtrRef.hxx @@ -91,7 +91,7 @@ void esignal::LockSharedPtrRef::removeData() { } template -void esignal::LockSharedPtrRef::disconnect(std::size_t _uid) { +void esignal::LockSharedPtrRef::disconnect(size_t _uid) { ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [START] " << _uid); if (m_counter == nullptr) { ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [STOP] No counter"); diff --git a/esignal/details/Signal.hxx b/esignal/details/Signal.hxx index 23aa935..39ec0f1 100644 --- a/esignal/details/Signal.hxx +++ b/esignal/details/Signal.hxx @@ -9,9 +9,6 @@ #include -#undef __class__ -#define __class__ "Signal" - template esignal::Signal::Signal(ObserverConnection _countObs): esignal::Base(_countObs), @@ -19,8 +16,6 @@ esignal::Signal::Signal(ObserverConnection _countObs): // nothing to do } - - template void esignal::Signal::emit(const T_ARGS&... _args) { #ifdef DEBUG @@ -78,7 +73,7 @@ void esignal::Signal::removeIfPossible() { } template -void esignal::Signal::disconnect(std::size_t _uid) { +void esignal::Signal::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; @@ -181,8 +176,3 @@ bool esignal::Signal::ExecutorShared::isSharedPtr(const std::shared_p } return false; } - -#undef __class__ -#define __class__ nullptr - - diff --git a/lutin_esignal.py b/lutin_esignal.py index ebdc80f..eac590f 100644 --- a/lutin_esignal.py +++ b/lutin_esignal.py @@ -55,7 +55,10 @@ def create(target, module_name): 'esignal/details/RefCount.hxx', ]) my_module.compile_version("c++", 2011) - my_module.add_module_depend(['etk']) + my_module.add_module_depend([ + 'etk', + 'ememory' + ]) my_module.add_path(tools.get_current_path(__file__)) my_module.compile_flags('c++', [ "-DESIGNAL_VERSION=\"\\\"" + tools.version_to_string(get_version()) + "\\\"\"" diff --git a/test/test_isignal.cpp b/test/test_isignal.cpp index 29436ba..32325a2 100644 --- a/test/test_isignal.cpp +++ b/test/test_isignal.cpp @@ -103,25 +103,25 @@ TEST(test_isignal_counter, localbasicInterfaceGetListSignal) { list.push_back("int"); list.push_back("string"); list.push_back("float"); - EXPECT_EQ(localClass.signalGetAll(), list); + EXPECT_EQ(localClass.signal.getAll(), list); } TEST(test_isignal_counter, localbasicInterfaceDisconnectNullPtr) { testISignal localClass; - localClass.signalDisconnect(nullptr); + localClass.signal.disconnect(nullptr); } TEST(test_isignal_counter, localbasicInterfaceDisconnectSharedPtr) { testISignal localClass; std::shared_ptr tmp = std::make_shared(); - localClass.signalDisconnect(tmp); + localClass.signal.disconnect(tmp); EXPECT_EQ(localClass.m_signalInt.size(), 0); EXPECT_EQ(localClass.m_signalInt.empty(), true); localClass.m_signalInt.connect(tmp, &testCallbackIShared::callbackConstInt); EXPECT_EQ(localClass.m_signalInt.size(), 1); EXPECT_EQ(localClass.m_signalInt.empty(), false); localClass.m_signalInt.emit(34567); - localClass.signalDisconnect(tmp); + localClass.signal.disconnect(tmp); EXPECT_EQ(localClass.m_signalInt.size(), 0); EXPECT_EQ(localClass.m_signalInt.empty(), true); }