8 Commits
0.1.0 ... 0.2.0

37 changed files with 738 additions and 183 deletions

View File

@@ -63,14 +63,14 @@ before_script:
- ./ci/build_send.py --tag=$TAG --status=START;
script:
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE esignal-test; STATUS=$?
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE esignal-*; STATUS=$?
- ./ci/build_send.py --tag=$TAG --status="$STATUS";
after_script:
- if [ "$GCOV" != "" ]; then
./ci/warning_send.py --find-path ./out/Linux_x86_64/$CONF/build/$BUILDER/esignal/;
fi
- ./out/Linux_x86_64/$CONF/staging/$BUILDER/esignal-test/esignal-test.app/bin/esignal-test --etk-log-level=3 | tee out_test.txt
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE esignal-test?run:--elog-level=3 | tee out_test.txt
- if [ "$GCOV" != "" ]; then
./ci/test_send.py --file=out_test.txt;
lutin -C -P -t $TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF -p esignal?gcov;

72
doc/build.md Normal file
View File

@@ -0,0 +1,72 @@
Build lib & build sample {#esignal_build}
========================
@tableofcontents
Download: {#esignal_build_download}
=========
esignal use some tools to manage source and build it:
lutin (build-system): {#esignal_build_download_lutin}
---------------------
```{.sh}
pip install lutin --user
# optionnal dependency of lutin (manage image changing size for application release
pip install pillow --user
```
dependency: {#esignal_build_download_dependency}
-----------
```{.sh}
mkdir framework
cd framework
git clone https://github.com/atria-soft/elog.git
git clone https://github.com/atria-soft/etk.git
git clone https://github.com/atria-soft/ememory.git
cd ..
```
sources: {#esignal_build_download_sources}
--------
```{.sh}
cd framework
git clone https://github.com/atria-soft/esignal.git
cd ..
```
Build: {#esignal_build_build}
======
library: {#esignal_build_build_library}
--------
```{.sh}
lutin -mdebug esignal
```
Sample: {#esignal_build_build_sample}
-------
```{.sh}
lutin -mdebug esignal-sample
lutin -mdebug esignal-test
```
Or simple:
```{.sh}
lutin -mdebug esignal-*
```
Run sample: {#esignal_build_run_sample}
===========
```{.sh}
lutin -mdebug esignal-sample?run
```

54
doc/mainpage.md Normal file
View File

@@ -0,0 +1,54 @@
ESIGNAL library {#mainpage}
===============
@tableofcontents
What is ESIGNAL, and how can I use it? {#esignal_mainpage_what}
======================================
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_mainpage_language}
=============================
ESIGNAL is written in C++.
Are there any licensing restrictions? {#esignal_mainpage_restriction}
=====================================
ESIGNAL is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
License (APACHE-2.0) {#esignal_mainpage_license}
====================
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
<http://www.apache.org/licenses/LICENSE-2.0>
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.
Other pages {#eproperty_mainpage_sub_page}
===========
- @ref esignal_build
- @ref esignal_tutorial
- [**ewol coding style**](http://atria-soft.github.io/ewol/ewol_coding_style.html)

112
doc/tutorial.md Normal file
View File

@@ -0,0 +1,112 @@
Tutorial {#esignal_tutorial}
========
@tableofcontents
Declare a Signal: {#esignal_declare}
=================
Declaring a signal is really simple, just include the esignal file:
@snippet sampleAll.cpp esignal_sample_declare
You can now declare your signals. We have basicly declare some basic signal type:
- void
- bool
- std::string / std::u32string
- int8_t / int16_t / int32_t / int64_t
- uint8_t / uint16_t / uint32_t / uint64_t
- float / double
- vec2 / bvec2 / ivec2 / uivec2
- vec3 / bvec3 / ivec3 / uivec3
- etk::Color<unsigned char,4>
- etk::Color<unsigned char,3>
- etk::Color<float,4>
- etk::Color<float,3>
To declare a signal with 'void' type:
@snippet sampleAll.cpp esignal_sample_declare_void
To declare a signal with 'int32_t' type:
@snippet sampleAll.cpp esignal_sample_declare_int
To declare a signal with 'string' type:
@snippet sampleAll.cpp esignal_sample_declare_string
Connecting on a signal {#esignal_connection}
======================
We have some way to connect on a signals depending on where we do the connection.
Connection and basic emition {#esignal_connection_base}
----------------------------
Declare the signal:
@snippet sampleAll.cpp esignal_sample_connection_simple_connection_declare
Declare a generic fuction:
@snippet sampleAll.cpp esignal_sample_connection_simple_extern_function
Connect a generic function:
@snippet sampleAll.cpp esignal_sample_connection_simple_connection_function
Or simply connect a lambda function:
@snippet sampleAll.cpp esignal_sample_connection_simple_connection_lambda
And now, we can emit a simple signal:
@snippet sampleAll.cpp esignal_sample_connection_simple_emit
You can see that all connection return a esignal::Connection value. This is an handle that can not be copiable, but only movable, While this handle is alive, the connection is allive too.
The to remove a connection, we only need to remive the handle or call the esignal::Connection::disconnect fucntion.
To disconnect a signal, it is very simple:
@snippet sampleAll.cpp esignal_sample_connection_simple_disconnect
This Will generate this simple sample code:
@snippet sampleAll.cpp esignal_sample_connection_simple
Connection on class member function {#esignal_connection_class}
-----------------------------------
Declare class fuction:
@snippet sampleAll.cpp esignal_sample_class_connection_callback
For direct connection, you need to have a 'const ref' on the parameter (internal helper design) to bind on the signal
Now you can nonnect the functions:
@snippet sampleAll.cpp esignal_sample_class_connection_callback_connect
This Will generate this simple sample code:
@snippet sampleAll.cpp esignal_sample_class_connection
Connection on std::shared_ptr<class> member function {#esignal_connection_shared}
----------------------------------------------------
std::hared_ptr have intrinsec knoledge of alive pointer, then, if you do not need to remove connection while the shared_ptr is alive, just connect it like:
@snippet sampleAll.cpp esignal_sample_shared_connection
Create new Signal {#esignal_create}
=================
If the signal is not in the list: @ref esignal_declare, you need to declare it yourself. This is due to optimise the compilation time,
in C++ when we inserte many template with all the implementation, the compilation time increase, the we decide to optimise the build time.
Create a new custum signal:
@snippet sampleAll.cpp esignal_sample_new_declare
Connect on the Signal:
@snippet sampleAll.cpp esignal_sample_new_lambda
Emit a Signal:
@snippet sampleAll.cpp esignal_sample_new_emit
This might work good, but at this point the compilation is OK, but not the linking ==> we need to declare the implementation of the signal:
@snippet sampleAll.cpp esignal_sample_new_register
This Will generate this simple sample code:
@snippet sampleAll.cpp esignal_sample_new

34
doxy_esignal.py Normal file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/python
import os
import doxy.module as module
import doxy.debug as debug
import doxy.tools as tools
def create(target, module_name):
my_module = module.Module(__file__, module_name)
my_module.set_version([0,1,"dev"])
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.add_path([
module_name,
"doc",
])
my_module.add_sample_path([
"sample",
])
my_module.add_module_depend([
'etk',
'ememory',
])
my_module.add_exclude_symbols([
'*operator<<*',
])
my_module.add_exclude_file([
'debug.h',
])
my_module.add_file_patterns([
'*.h',
'*.md',
])
return my_module

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -17,7 +17,13 @@
#include <mutex>
#include <esignal/LockSharedPtrRef.h>
/**
* @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 {
public:
using ObserverConnection = std::function<void(size_t)>; //!< Define an Observer of the number of observer
@@ -25,21 +31,32 @@ namespace esignal {
esignal::LockSharedPtrRef<esignal::Base> 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:
/**
* @brief Basic constructor:
* @param[in] _countObs Observer on the number of connection availlable
*/
Base(ObserverConnection _countObs = nullptr);
//! @brief Copy constructor:
Base(const Base&) = delete;
//! @brief Move constructor
Base(Base&& _obj) = delete;
Base(Base&&) = delete;
/**
* @brief Virtualize the destructor
* @internal
*/
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<void>& _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 +68,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);

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,7 +13,7 @@ esignal::Connection::Connection():
}
esignal::Connection::Connection(const esignal::LockSharedPtrRef<esignal::Base>& _ref, std::size_t _id):
esignal::Connection::Connection(const esignal::LockSharedPtrRef<esignal::Base>& _ref, size_t _id):
m_signalRefUnique(_ref),
m_uid(_id) {

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -22,21 +22,43 @@ namespace esignal {
*/
class Connection {
public:
//! @brief Constructor (no link)
/**
* @brief Constructor (no link)
*/
Connection();
//! @brief Constructor (link)
Connection(const esignal::LockSharedPtrRef<esignal::Base>& _ref, std::size_t _id);
//! @brief Move Constructor
/**
* @brief Constructor (link)
* @param[in] _ref Reference ID of the Signal extern handle
* @param[in] _id Id of the Connection handle
*/
Connection(const esignal::LockSharedPtrRef<esignal::Base>& _ref, size_t _id);
/**
* @brief Move Constructor
* @param[in] _obj Connection Object to move
*/
Connection(Connection&& _obj);
//! @brief Move operator.
/**
* @brief Move operator.
* @param[in] _obj Connection Object to move
* @return Local reference on the local object (moved)
*/
Connection& operator=(Connection&& _obj);
//! @brief Copy constructor (REMOVED)
/**
* @brief Copy constructor (REMOVED)
*/
Connection(const Connection&) = delete;
//! @brief Copy operator (REMOVED)
/**
* @brief Copy operator (REMOVED)
* @return Reference on this
*/
Connection& operator=(const Connection&) = delete;
//! @brief Destructor.
/**
* @brief Destructor.
*/
~Connection();
//! @brief Disconnect the signal.
/**
* @brief Disconnect the signal.
*/
void disconnect();
/**
* @brief Check if the connection is alive or signal removed
@@ -46,7 +68,7 @@ namespace esignal {
bool isConnected();
private:
esignal::LockSharedPtrRef<esignal::Base> 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.
};
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -14,9 +14,6 @@
#include <esignal/Signal.h>
#include <esignal/Interface.h>
#undef __class__
#define __class__ "ISignal<T_ARGS>"
namespace esignal {
/**
* @brief Sigla same as @ref esignal::Signal withe a name and a description to manage a list of signals.
@@ -31,7 +28,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 +37,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 +50,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,10 +67,7 @@ esignal::ISignal<T_ARGS...>::ISignal(CLASS_TYPE* _class,
m_description(_description) {
// add a reference on the current signal ...
if (m_signalInterfaceLink != nullptr) {
m_signalInterfaceLink->signalAdd(this);
m_signalInterfaceLink->signals.add(this);
}
}
#undef __class__
#define __class__ nullptr

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -9,39 +9,16 @@
#include <vector>
#include <map>
#include <esignal/InterfaceData.h>
namespace esignal {
class Base;
/**
* @brief Interface to collect the Signal list (for abstarction connection)
* It create a simple "signals" member that permit to access at the signalproperties.
*/
class Interface {
friend class esignal::Base; // to register parameter in the list.
private:
std::vector<esignal::Base*> m_list; //!< list of availlable Parameters
public:
/**
* @brief Constructor.
*/
Interface();
/**
* @brief Destructor.
*/
virtual ~Interface();
/**
* @brief Register a parameter class pointer in the List of parameters
* @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);
/**
* @brief Get All the signal list:
* @return vector on all the signals names
*/
std::vector<std::string> signalGetAll() const;
/**
* @brief Remove binding on all event class.
* @param[in] _sharedPtr sharedPtr to unlink (no type needed ...).
*/
void signalDisconnect(const std::shared_ptr<void>& _sharedPtr);
esignal::InterfaceData signals; //!< Interface to access at all signals properties...
};
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -8,19 +8,19 @@
#include <memory>
#include <esignal/debug.h>
#include <esignal/Interface.h>
#include <esignal/InterfaceData.h>
#include <esignal/Base.h>
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<std::string> esignal::Interface::signalGetAll() const {
std::vector<std::string> esignal::InterfaceData::getAll() const {
std::vector<std::string> out;
for (auto &it : m_list) {
if(it != nullptr) {
@@ -50,7 +50,7 @@ std::vector<std::string> esignal::Interface::signalGetAll() const {
return out;
}
void esignal::Interface::signalDisconnect(const std::shared_ptr<void>& _object) {
void esignal::InterfaceData::disconnect(const std::shared_ptr<void>& _object) {
if (_object == nullptr) {
ESIGNAL_ERROR("Input ERROR nullptr pointer Object ...");
return;
@@ -62,3 +62,5 @@ void esignal::Interface::signalDisconnect(const std::shared_ptr<void>& _object)
it->disconnectShared(_object);
}
}

54
esignal/InterfaceData.h Normal file
View File

@@ -0,0 +1,54 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <map>
namespace esignal {
class Base;
/**
* @brief Interface data to collect the Signal list (for abstarction connection)
*/
class InterfaceData {
private:
std::vector<esignal::Base*> m_list; //!< list of availlable Parameters
public:
/**
* @brief Constructor.
*/
InterfaceData();
/**
* @brief Destructor.
*/
virtual ~InterfaceData();
/**
* @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 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<std::string> getAll() const;
/**
* @brief Remove binding on all event class.
* @param[in] _sharedPtr sharedPtr to unlink (no type needed ...).
*/
void disconnect(const std::shared_ptr<void>& _sharedPtr);
};
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -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 TYPE>
class LockSharedPtrRef {
@@ -35,7 +35,7 @@ namespace esignal {
LockSharedPtrRef(const LockSharedPtrRef<TYPE>& _obj);
/**
* @brief Copy operator (It copy the counter and increment the it).
* @param[in] _obj objetc to copy.
* @param[in] _obj object to copy.
* @return Reference of this
*/
LockSharedPtrRef& operator=(const LockSharedPtrRef<TYPE>& _obj);
@@ -46,8 +46,9 @@ namespace esignal {
LockSharedPtrRef(LockSharedPtrRef<TYPE>&& _obj);
/**
* @brief Copy operator (force move) ==> removed
* @return Reference of this
*/
LockSharedPtrRef& operator=(LockSharedPtrRef<TYPE>&& _obj) = delete;
LockSharedPtrRef& operator=(LockSharedPtrRef<TYPE>&&) = delete;
/**
* @brief Destructor of the class (decrement the counter and remove it if it is the last one...)
*/
@@ -60,7 +61,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

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -21,34 +21,55 @@ 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;
//! @brief Copy operator (REMOVED)
/**
* @brief Copy operator (REMOVED)
* @return Reference on this
*/
RefCount& operator=(RefCount) = delete;
//! @previous
RefCount& operator=(const RefCount& _obj) = delete;
/**
* @brief Copy operator (REMOVED)
* @return Reference on this
*/
RefCount& operator=(const RefCount&) = delete;
//! @brief Move constructor (REMOVED)
RefCount(RefCount&& _obj) = delete;
//! @brief Move operator (REMOVED)
RefCount& operator=(RefCount&& _obj) = delete;
RefCount(RefCount&&) = delete;
/**
* @brief Move operator (REMOVED)
* @return Reference on this
*/
RefCount& operator=(RefCount&&) = delete;
//! @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
* @return Number of element connected when decrement
*/
int64_t dec();
//!< @brief Get number of connected
/**
* @brief Get number of connected
* @return The number of element connected on it
*/
int64_t getCount() const;
//!< @brief Remove the data
//! @brief Remove the data
void remove();
//!< @brief Get the recoreded data
/**
* @brief Get the recoreded data
* @return The pointer of the data
*/
TYPE* get();
};
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -19,9 +19,6 @@
#include <utility>
#include <mutex>
#undef __class__
#define __class__ "Signal<T_ARGS>"
namespace esignal {
/**
* @brief Basic signal base
@@ -35,21 +32,36 @@ 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<class CLASS_TYPE, class FUNC_TYPE>
Signal(CLASS_TYPE* _class, FUNC_TYPE _func);
//! @brief Copy constructor (REMOVED)
Signal(const Signal&) = delete;
//! @brief Copy operator (REMOVED)
/**
* @brief Copy operator (REMOVED)
* @return Reference on this
*/
Signal& operator=(Signal) = delete;
Signal& operator=(const Signal& _obj) = delete;
/**
* @brief Copy operator (REMOVED)
* @return Reference on this
*/
Signal& operator=(const Signal&) = delete;
//! @brief Move constructor (REMOVED)
Signal(Signal&& _obj) = delete;
//! @brief Move operator
Signal& operator=(Signal&& _obj) = delete;
Signal(Signal&&) = delete;
/**
* @brief Move operator (REMOVED)
* @return Reference on this
*/
Signal& operator=(Signal&&) = delete;
private:
/**
* @brief Executor: Class to manage the UID and basic value of an observer
@@ -87,7 +99,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:
@@ -104,14 +115,15 @@ namespace esignal {
* @brief Emit the data on the observer.
* @param[in] _values... Multiple value needed to send on observers
*/
virtual void emit(const T_ARGS&... _values);
void emit(const T_ARGS&... _values) override;
public:
virtual bool isSharedPtr(const std::shared_ptr<void>& _obj);
bool isSharedPtr(const std::shared_ptr<void>& _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 +132,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<class CLASS_TYPE, class FUNC_TYPE, class... FUNC_ARGS_TYPE>
esignal::Connection connect(CLASS_TYPE* _class,
@@ -129,7 +142,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<class PARENT_CLASS_TYPE, class CLASS_TYPE, typename... FUNC_ARGS_TYPE>
void connect(const std::shared_ptr<PARENT_CLASS_TYPE>& _class,
@@ -142,14 +155,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<void>& _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<void>& _obj) override;
/**
* @brief Get the number of observers connected on the signal.
* @return The count of observer.
@@ -174,7 +195,7 @@ template< class OBSERVER_TYPE >
esignal::Connection esignal::Signal<T_ARGS...>::connect(OBSERVER_TYPE&& _observer ) {
ESIGNAL_DEBUG("esignal: '" << getName() << "' try connect: '" << getName() << "' (observer)");
std::unique_ptr<Executor> executer(new Executor(std::forward<OBSERVER_TYPE>(_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 +217,7 @@ esignal::Connection esignal::Signal<T_ARGS...>::connect(CLASS_TYPE* _class,
std::unique_ptr<Executor> 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());
@@ -240,6 +261,3 @@ esignal::Signal<T_ARGS...>::Signal(CLASS_TYPE* _class,
m_callInProgress(0) {
// nothing to do
}
#undef __class__
#define __class__ nullptr

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -11,8 +11,6 @@
#include <etk/math/Vector3D.h>
#include <etk/Color.h>
#undef __class__
#define __class__ "ISignal<void>"
// void generic signal
template class esignal::ISignal<>;
// std generic signal

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -10,9 +10,6 @@
#include <esignal/ISignal.h>
#include <esignal/details/Signal.hxx>
#undef __class__
#define __class__ "ISignal<T_ARGS>"
template<class... T_ARGS>
esignal::ISignal<T_ARGS...>::ISignal(esignal::Interface* _signalInterfaceLink,
const std::string& _name,
@@ -22,14 +19,14 @@ esignal::ISignal<T_ARGS...>::ISignal(esignal::Interface* _signalInterfaceLink,
m_description(_description) {
// add a reference on the current signal ...
if (m_signalInterfaceLink != nullptr) {
m_signalInterfaceLink->signalAdd(this);
m_signalInterfaceLink->signals.add(this);
}
}
template<class... T_ARGS>
esignal::ISignal<T_ARGS...>::~ISignal() {
if (m_signalInterfaceLink != nullptr) {
m_signalInterfaceLink->signalRemove(this);
m_signalInterfaceLink->signals.remove(this);
}
}
@@ -43,6 +40,3 @@ const std::string& esignal::ISignal<T_ARGS...>::getDescription() const {
return m_description;
}
#undef __class__
#define __class__ nullptr

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -91,7 +91,7 @@ void esignal::LockSharedPtrRef<TYPE>::removeData() {
}
template<class TYPE>
void esignal::LockSharedPtrRef<TYPE>::disconnect(std::size_t _uid) {
void esignal::LockSharedPtrRef<TYPE>::disconnect(size_t _uid) {
ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [START] " << _uid);
if (m_counter == nullptr) {
ESIGNAL_VERBOSE("LockSharedPtrRef disconnect [STOP] No counter");

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -11,8 +11,6 @@
#include <etk/math/Vector3D.h>
#include <etk/Color.h>
#undef __class__
#define __class__ "Signal<void>"
// void generic signal
template class esignal::Signal<>;
// std generic signal

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -9,9 +9,6 @@
#include <esignal/Signal.h>
#undef __class__
#define __class__ "Signal<T_ARGS>"
template<typename... T_ARGS>
esignal::Signal<T_ARGS...>::Signal(ObserverConnection _countObs):
esignal::Base(_countObs),
@@ -19,8 +16,6 @@ esignal::Signal<T_ARGS...>::Signal(ObserverConnection _countObs):
// nothing to do
}
template<typename... T_ARGS>
void esignal::Signal<T_ARGS...>::emit(const T_ARGS&... _args) {
#ifdef DEBUG
@@ -78,7 +73,7 @@ void esignal::Signal<T_ARGS...>::removeIfPossible() {
}
template<typename... T_ARGS>
void esignal::Signal<T_ARGS...>::disconnect(std::size_t _uid) {
void esignal::Signal<T_ARGS...>::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<T_ARGS...>::ExecutorShared::isSharedPtr(const std::shared_p
}
return false;
}
#undef __class__
#define __class__ nullptr

34
lutin_esignal-sample.py Normal file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/python
import lutin.module as module
import lutin.tools as tools
import datetime
def get_type():
return "BINARY"
def get_sub_type():
return "SAMPLE"
def get_desc():
return "e-signal sample 1"
def get_licence():
return "APACHE-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([
'sample/sampleAll.cpp'
])
my_module.add_module_depend(['esignal', 'test-debug'])
return my_module

View File

@@ -33,7 +33,7 @@ def create(target, module_name):
my_module.add_src_file([
'esignal/debug.cpp',
'esignal/Connection.cpp',
'esignal/Interface.cpp',
'esignal/InterfaceData.cpp',
'esignal/Base.cpp',
'esignal/details/LockSharedPtrRef.cpp',
'esignal/details/RefCount.cpp',
@@ -43,6 +43,7 @@ def create(target, module_name):
my_module.add_header_file([
'esignal/debug.h',
'esignal/Interface.h',
'esignal/InterfaceData.h',
'esignal/Base.h',
'esignal/Signal.h',
'esignal/ISignal.h',
@@ -55,7 +56,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()) + "\\\"\""

19
monk_esignal.py Normal file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/python
import monkModule
import monkTools as tools
import os
def get_desc():
return "E-signal simple signal syncronous library"
def create():
# module name is 'ewol' and type binary.
myModule = monkModule.Module(__file__, 'esignal', 'LIBRARY')
# enable doculentation :
myModule.set_website("http://atria-soft.github.io/esignal/")
myModule.set_website_sources("http://github.com/atria-soft/esignal/")
myModule.set_path(os.path.join(tools.get_current_path(__file__), "esignal"))
myModule.set_path_general_doc(os.path.join(tools.get_current_path(__file__), "doc"))
# add the currrent module at the
return myModule

156
sample/sampleAll.cpp Normal file
View File

@@ -0,0 +1,156 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/etk.h>
#include <test-debug/debug.h>
//! [esignal_sample_declare]
#include <esignal/Signal.h>
//! [esignal_sample_declare]
void declareSignals() {
//! [esignal_sample_declare_int]
esignal::Signal<int32_t> signalInt;
//! [esignal_sample_declare_int]
//! [esignal_sample_declare_void]
esignal::Signal<> signalVoid;
//! [esignal_sample_declare_void]
//! [esignal_sample_declare_string]
esignal::Signal<std::string> signalString;
//! [esignal_sample_declare_string]
}
//! [esignal_sample_connection_simple]
//! [esignal_sample_connection_simple_extern_function]
void localCallBack(int32_t _val) {
TEST_PRINT("Callback Local the value is : " << _val);
}
//! [esignal_sample_connection_simple_extern_function]
void basicConnection() {
// Create the signal
//! [esignal_sample_connection_simple_connection_declare]
esignal::Signal<int32_t> signalValue;
//! [esignal_sample_connection_simple_connection_declare]
// Connect the signal function
//! [esignal_sample_connection_simple_connection_function]
esignal::Connection con1 = signalValue.connect(&localCallBack);
//! [esignal_sample_connection_simple_connection_function]
// Connect the signal Lambda
//! [esignal_sample_connection_simple_connection_lambda]
esignal::Connection con2 = signalValue.connect(
[](int32_t _val) {
TEST_PRINT("Callback 1 the value is : " << _val);
});
//! [esignal_sample_connection_simple_connection_lambda]
// Emit the signal
//! [esignal_sample_connection_simple_emit]
signalValue.emit(1001001);
//! [esignal_sample_connection_simple_emit]
// Disconnect the connection n°1
//! [esignal_sample_connection_simple_disconnect]
con1.disconnect();
//! [esignal_sample_connection_simple_disconnect]
// Second emit to check disconnection
signalValue.emit(2002002);
}
//! [esignal_sample_connection_simple]
//*********************************************************************************************
//! [esignal_sample_class_connection]
//! [esignal_sample_class_connection_callback]
class TmpClass {
public:
void localCallBack(const int32_t& _val) {
TEST_PRINT("Callback Local the value is : " << _val);
}
void localCallBackSecond(const int32_t& _val, const std::string& _otherValue) {
TEST_PRINT("Callback 2 Local the value is : " << _val << " with perso: '" << _otherValue << "'");
}
};
//! [esignal_sample_class_connection_callback]
void classConnection() {
// Create the signal
esignal::Signal<int32_t> signalValue;
// Declare the class
TmpClass myClass;
// Connect signals
//! [esignal_sample_class_connection_callback_connect]
esignal::Connection con1 = signalValue.connect(&myClass, &TmpClass::localCallBack);
esignal::Connection con2 = signalValue.connect(&myClass, &TmpClass::localCallBackSecond, "Hello, HowAreYou");
//! [esignal_sample_class_connection_callback_connect]
// Emit sample signals
signalValue.emit(4004004);
}
//! [esignal_sample_class_connection]
//! [esignal_sample_shared_connection]
void sharedConnection() {
// Create the signal
esignal::Signal<int32_t> signalValue;
// Declare the class
std::shared_ptr<TmpClass> myClassShared = std::make_shared<TmpClass>();
// Connect signals
signalValue.connect(myClassShared, &TmpClass::localCallBack);
// Emit sample signals
signalValue.emit(7007007);
}
//! [esignal_sample_shared_connection]
//! [esignal_sample_new]
void newSignal() {
// Declare new signal
//! [esignal_sample_new_declare]
esignal::Signal<int32_t, std::string> signalCustum;
//! [esignal_sample_new_declare]
// Connect a lambda
//! [esignal_sample_new_lambda]
esignal::Connection con2 = signalCustum.connect(
[](int32_t _val, std::string _val2) {
TEST_PRINT("lambda callback: " << _val << " vel2=" << _val2);
});
//! [esignal_sample_new_lambda]
// Example emit
//! [esignal_sample_new_emit]
signalCustum.emit(1001001, "plop");
//! [esignal_sample_new_emit]
}
// do it in a single C++: Implementation of signal
//! [esignal_sample_new_register]
#include <esignal/details/Signal.hxx>
template class esignal::Signal<int32_t, std::string>;
//! [esignal_sample_new_register]
//! [esignal_sample_new]
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
TEST_INFO("declare [START] ***************************");
declareSignals();
TEST_INFO("declare [STOP] ***************************");
TEST_INFO("Basic connection [START] ***************************");
basicConnection();
TEST_INFO("Basic connection [STOP] ***************************");
TEST_INFO("class connection [START] ***************************");
classConnection();
TEST_INFO("class connection [STOP] ***************************");
TEST_INFO("shared_ptr connection [START] ***************************");
sharedConnection();
TEST_INFO("shared_ptr connection [STOP] ***************************");
return 0;
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -12,9 +12,6 @@
#include <test-debug/debug.h>
#include <gtest/gtest.h>
#undef __class__
#define __class__ "esignal-test"
int main(int _argc, const char *_argv[]) {
::testing::InitGoogleTest(&_argc, const_cast<char **>(_argv));
etk::init(_argc, _argv);

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -14,9 +14,6 @@
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_isignal"
class testISignal : public esignal::Interface {
public:
esignal::ISignal<int32_t> m_signalInt;
@@ -103,25 +100,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.signals.getAll(), list);
}
TEST(test_isignal_counter, localbasicInterfaceDisconnectNullPtr) {
testISignal localClass;
localClass.signalDisconnect(nullptr);
localClass.signals.disconnect(nullptr);
}
TEST(test_isignal_counter, localbasicInterfaceDisconnectSharedPtr) {
testISignal localClass;
std::shared_ptr<testCallbackIShared> tmp = std::make_shared<testCallbackIShared>();
localClass.signalDisconnect(tmp);
localClass.signals.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.signals.disconnect(tmp);
EXPECT_EQ(localClass.m_signalInt.size(), 0);
EXPECT_EQ(localClass.m_signalInt.empty(), true);
}

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,9 +13,6 @@
#include <memory>
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_signal_class_func"
class testCallback {
public:
int32_t m_int32;

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,9 +13,6 @@
#include <memory>
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_signal_counter"
class testCounter {
public:
esignal::Signal<std::string> m_signal;

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,10 +13,6 @@
#include <memory>
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_signal_static_func"
static esignal::Signal<int32_t>* signalll;
static int32_t tmpRetInt32 = 0;

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,9 +13,6 @@
#include <memory>
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_signal_class_func"
class testCallbackShared : public std::enable_shared_from_this<testCallbackShared> {
public:
int32_t m_int32;

View File

@@ -1,4 +1,4 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2016, Edouard DUPIN, all right reserved
@@ -13,10 +13,6 @@
#include <memory>
#include <test-debug/debug.h>
#undef __class__
#define __class__ "test_signal_static_func"
static int32_t tmpRetInt32 = 0;
static std::string tmpRetString = "";
static bool tmpRetVoid = false;