[DEV] nearly a good version
This commit is contained in:
parent
1fcf22bf03
commit
c4eb2635a3
@ -11,30 +11,36 @@
|
||||
#include <esignal/Interface.h>
|
||||
#include <esignal/Base.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
int32_t esignal::Base::m_uidSignal = 0;
|
||||
int32_t esignal::Base::m_signalCallLevel = 0;
|
||||
#endif
|
||||
size_t esignal::Base::s_uid = 0;
|
||||
|
||||
esignal::Base::Base() :
|
||||
m_shared(this) {
|
||||
|
||||
esignal::Base::Base(esignal::Interface& _signalInterfaceLink,
|
||||
const std::string& _name,
|
||||
const std::string& _description,
|
||||
bool _periodic) :
|
||||
m_signalInterfaceLink(_signalInterfaceLink),
|
||||
m_name(_name),
|
||||
m_description(_description),
|
||||
m_callInProgress(0),
|
||||
m_someOneRemoveInCall(false),
|
||||
m_periodic(_periodic) {
|
||||
// add a reference on the current signal ...
|
||||
m_signalInterfaceLink.signalAdd(this);
|
||||
}
|
||||
esignal::Base::~Base() {
|
||||
m_shared.removeData();
|
||||
}
|
||||
|
||||
|
||||
const std::string& esignal::Base::getName() const {
|
||||
static std::string noValue;
|
||||
return noValue;
|
||||
}
|
||||
|
||||
const std::string& esignal::Base::getDescription() const {
|
||||
static std::string noValue;
|
||||
return noValue;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& esignal::operator <<(std::ostream& _os, const esignal::Base& _obj) {
|
||||
_os << _obj.getName();
|
||||
return _os;
|
||||
}
|
||||
|
||||
void esignal::Base::disconnect(const std::shared_ptr<void>& _obj) {
|
||||
|
||||
}
|
||||
|
||||
const char* esignal::logIndent(int32_t _iii) {
|
||||
static const char g_val[] = " ";
|
||||
|
@ -7,45 +7,41 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esignal/Interface.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
#include <esignal/LockSharedPtrRef.h>
|
||||
|
||||
namespace esignal {
|
||||
#undef __class__
|
||||
#define __class__ "Signal<T>"
|
||||
class Base {
|
||||
protected:
|
||||
#ifdef DEBUG
|
||||
static int32_t m_uidSignal;
|
||||
static int32_t m_signalCallLevel;
|
||||
#endif
|
||||
esignal::Interface& m_signalInterfaceLink;
|
||||
std::string m_name;
|
||||
std::string m_description;
|
||||
int32_t m_callInProgress;
|
||||
bool m_someOneRemoveInCall;
|
||||
bool m_periodic;
|
||||
LockSharedPtrRef<Base> m_shared;
|
||||
static size_t s_uid;
|
||||
public:
|
||||
/**
|
||||
* @brief Create a parameter with a specific type.
|
||||
* @param[in] _signalInterfaceLink reference on the signal list.
|
||||
* @param[in] _name Static name of the parameter.
|
||||
* @param[in] _description description of the parameter.
|
||||
* @param[in] _periodic Customisation of the log display tag at true to down debug lebel at verbose.
|
||||
*/
|
||||
Base(esignal::Interface& _signalInterfaceLink,
|
||||
const std::string& _name,
|
||||
const std::string& _description = "",
|
||||
bool _periodic = false);
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~Base() { };
|
||||
Base();
|
||||
// copy constructor:
|
||||
Base(const Base&) = delete;
|
||||
// copy operator:
|
||||
//Base& operator=(Base) = delete;
|
||||
//Base& operator=(const Base& _obj) = delete;
|
||||
// Move constructor
|
||||
Base(Base&& _obj) = delete;
|
||||
// Move operator
|
||||
//Base& operator=(Base&& _obj) = delete;
|
||||
|
||||
const std::string& getName() const {
|
||||
return m_name;
|
||||
}
|
||||
const std::string& getDescription() const {
|
||||
return m_description;
|
||||
}
|
||||
virtual void release(std::shared_ptr<void> _obj) = 0;
|
||||
virtual ~Base();
|
||||
virtual void disconnect(const std::shared_ptr<void>& _obj);
|
||||
virtual void disconnect(std::size_t _uid) = 0;
|
||||
|
||||
virtual const std::string& getName() const;
|
||||
virtual const std::string& getDescription() const;
|
||||
};
|
||||
std::ostream& operator <<(std::ostream& _os, const esignal::Base& _obj);
|
||||
const char* logIndent(int32_t _iii);
|
||||
|
58
esignal/Connection.h
Normal file
58
esignal/Connection.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
|
||||
namespace esignal {
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection():
|
||||
m_signalRefUnique(), m_uid(0) {
|
||||
|
||||
}
|
||||
Connection(LockSharedPtrRef<Base> _ref, std::size_t _id):
|
||||
m_signalRefUnique(_ref), m_uid(_id) {
|
||||
|
||||
}
|
||||
Connection(Connection&&) = default; // movable
|
||||
Connection& operator=(Connection&&) = default; // movable op
|
||||
Connection(const Connection&) = delete; // not copyable
|
||||
Connection& operator=(const Connection&) = delete; // no copy operator
|
||||
/*
|
||||
void set(Connection&& _obj) {
|
||||
disconnect();
|
||||
std::swap(m_signalRefUnique, _obj.m_signalRefUnique);
|
||||
std::swap(m_uid,_obj.m_uid);
|
||||
}
|
||||
*/
|
||||
~Connection() {
|
||||
m_signalRefUnique.disconnect(m_uid);
|
||||
m_uid = 0;
|
||||
}
|
||||
void disconnect() {
|
||||
m_signalRefUnique.disconnect(m_uid);
|
||||
m_uid = 0;
|
||||
}
|
||||
bool isConnected() {
|
||||
return m_signalRefUnique.isAlive();
|
||||
}
|
||||
private:
|
||||
LockSharedPtrRef<Base> m_signalRefUnique;
|
||||
std::size_t m_uid;
|
||||
};
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <esignal/Signal.h>
|
||||
#include <esignal/Interface.h>
|
||||
|
||||
namespace esignal {
|
||||
#undef __class__
|
||||
@ -27,122 +29,28 @@ namespace esignal {
|
||||
* @param[in] _signalInterfaceLink reference on the signal lister.
|
||||
* @param[in] _name Static name of the signal.
|
||||
* @param[in] _description Description of the signal.
|
||||
* @param[in] _periodic Customisation of the log display tag at true to down debug lebel at verbose.
|
||||
*/
|
||||
ISignal(esignal::Interface& _signalInterfaceLink,
|
||||
const std::string& _name,
|
||||
const std::string& _description = "",
|
||||
bool _periodic = false);
|
||||
const std::string& _description = ""):
|
||||
m_signalInterfaceLink(_signalInterfaceLink),
|
||||
m_name(_name),
|
||||
m_description(_description) {
|
||||
// add a reference on the current signal ...
|
||||
m_signalInterfaceLink.signalAdd(this);
|
||||
}
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~Signal();
|
||||
/**
|
||||
* @brief Bind a callback function to the current signal (generic methis (simplest))
|
||||
* @param[in] _obj Shared pointer on the caller object
|
||||
* @param[in] _func Link on the fuction that might be called (inside a class)
|
||||
* @example signalXXXX.bind(shared_from_this(), &ClassName::onCallbackXXX);
|
||||
*/
|
||||
template<class TYPE_CLASS, class TYPE, typename... TArgs>
|
||||
void bind(std::shared_ptr<TYPE_CLASS> _obj, void (TYPE::*_func)(const T&, TArgs...), TArgs... _args2) {
|
||||
std::shared_ptr<TYPE> obj2 = std::dynamic_pointer_cast<TYPE>(_obj);
|
||||
if (obj2 == nullptr) {
|
||||
ESIGNAL_ERROR("Can not bind signal ...");
|
||||
return;
|
||||
virtual ~ISignal() {
|
||||
m_signalInterfaceLink.signalRemove(this);
|
||||
}
|
||||
if (m_callInProgress == 0) {
|
||||
m_callerList.push_back(std::make_pair(std::weak_ptr<void>(_obj), std::bind(_func, obj2.get(), std::placeholders::_1, std::forward<TArgs>(_args2)...)));
|
||||
} else {
|
||||
m_callerListInCallback.push_back(std::make_pair(std::weak_ptr<void>(_obj), std::bind(_func, obj2.get(), std::placeholders::_1, std::forward<TArgs>(_args2)...)));
|
||||
const std::string& getName() const {
|
||||
return m_name;
|
||||
}
|
||||
const std::string& getDescription() const {
|
||||
return m_description;
|
||||
}
|
||||
/**
|
||||
* @brief Advanced binding a callback function to the current signal.
|
||||
* @param[in] _obj Shared pointer on the caller object
|
||||
* @param[in] _func functor to call (do it yourself)
|
||||
* @example signalXXXX.connect(shared_from_this(), std::bind(&ClassName::onCallbackXXX, this, std::placeholders::_1));
|
||||
*/
|
||||
void connect(std::shared_ptr<void> _obj, std::function<void(const T&)> _function );
|
||||
//! @previous
|
||||
void connect(std::function<void(const T&)> _function );
|
||||
/**
|
||||
* @brief Check if an object is registered in the Signal
|
||||
* @param[in] _obj shared pointer on the object
|
||||
* @return true The object is connected at this signal.
|
||||
* @return false The object is NOT connected on this signal.
|
||||
*/
|
||||
bool isRegistered(std::shared_ptr<void> _obj);
|
||||
/**
|
||||
* @brief remove link on the signal.
|
||||
* @param[in] _obj shared pointer on the removing object
|
||||
*/
|
||||
void release(std::shared_ptr<void> _obj);
|
||||
/**
|
||||
* @brief Generate a signal on all interface listening.
|
||||
* @param[in] _data data to emit
|
||||
*/
|
||||
void emit(const T& _data);
|
||||
size_t getNumberConnected();
|
||||
};
|
||||
#undef __class__
|
||||
#define __class__ "Signal<void>"
|
||||
template<> class Signal<void> : public esignal::Base {
|
||||
private:
|
||||
std::vector<std::pair<std::weak_ptr<void>, std::function<void()>>> m_callerList;
|
||||
std::vector<std::pair<std::weak_ptr<void>, std::function<void()>>> m_callerListInCallback;
|
||||
std::vector<std::function<void()>> m_callerListDirect;
|
||||
std::vector<std::function<void()>> m_callerListDirectInCallback;
|
||||
public:
|
||||
/**
|
||||
* @brief Create a signal with a specific 'void' type.
|
||||
* @param[in] _signalInterfaceLink reference on the signal lister.
|
||||
* @param[in] _name Static name of the signal.
|
||||
* @param[in] _description Description of the signal.
|
||||
* @param[in] _periodic Customisation of the log display tag at true to down debug lebel at verbose.
|
||||
*/
|
||||
Signal(esignal::Interface& _signalInterfaceLink,
|
||||
const std::string& _name,
|
||||
const std::string& _description = "",
|
||||
bool _periodic = false);
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~Signal();
|
||||
/**
|
||||
* @brief Bind a callback function to the current signal (generic methis (simplest))
|
||||
* @param[in] _obj Shared pointer on the caller object
|
||||
* @param[in] _func Link on the fuction that might be called (inside a class)
|
||||
* @example signalXXXX.connect(shared_from_this(), &ClassName::onCallbackXXX);
|
||||
*/
|
||||
template<class TYPE_CLASS, class TYPE, typename... TArgs>
|
||||
void bind(std::shared_ptr<TYPE_CLASS> _obj, void (TYPE::*_func)(TArgs...), TArgs... args2) {
|
||||
std::shared_ptr<TYPE> obj2 = std::dynamic_pointer_cast<TYPE>(_obj);
|
||||
if (obj2 == nullptr) {
|
||||
ESIGNAL_ERROR("Can not bind signal ...");
|
||||
return;
|
||||
}
|
||||
if (m_callInProgress == 0) {
|
||||
m_callerList.push_back(std::make_pair(std::weak_ptr<void>(_obj), std::bind(_func, obj2.get(), std::forward<TArgs>(args2)...)));
|
||||
} else {
|
||||
m_callerListInCallback.push_back(std::make_pair(std::weak_ptr<void>(_obj), std::bind(_func, obj2.get(), std::forward<TArgs>(args2)...)));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Advanced binding a callback function to the current signal.
|
||||
* @param[in] _obj Shared pointer on the caller object
|
||||
* @param[in] _func functor to call (do it yourself)
|
||||
* @example signalXXXX.connect(shared_from_this(), std::bind(&ClassName::onCallbackXXX, this, std::placeholders::_1));
|
||||
*/
|
||||
void connect(std::shared_ptr<void> _obj, std::function<void()> _function);
|
||||
//! @previous
|
||||
void connect(std::function<void()> _function);
|
||||
/**
|
||||
* @brief remove link on the signal.
|
||||
* @param[in] _obj shared pointer on the removing object
|
||||
*/
|
||||
void release(std::shared_ptr<void> _obj);
|
||||
void emit();
|
||||
size_t getNumberConnected();
|
||||
};
|
||||
#undef __class__
|
||||
#define __class__ nullptr
|
||||
|
@ -47,6 +47,15 @@ void esignal::Interface::signalUnBindAll(const std::shared_ptr<void>& _object) {
|
||||
if (it == nullptr) {
|
||||
continue;
|
||||
}
|
||||
it->release(_object);
|
||||
it->disconnect(_object);
|
||||
}
|
||||
}
|
||||
|
||||
void esignal::Interface::signalUnConnect(size_t _uid) {
|
||||
for(auto &it : m_list) {
|
||||
if (it == nullptr) {
|
||||
continue;
|
||||
}
|
||||
it->disconnect(_uid);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ namespace esignal {
|
||||
* @param[in] pointerOnParameter Pointer on the parameter that might be added.
|
||||
*/
|
||||
void signalAdd(esignal::Base* _pointerOnParameter);
|
||||
void signalRemove(esignal::Base* _pointerOnParameter);
|
||||
/**
|
||||
* @brief Get All the signal list:
|
||||
* @return vector on all the signals names
|
||||
@ -41,6 +42,7 @@ namespace esignal {
|
||||
* @param[in] _sharedPtr sharedPtr to unlink (no type needed ...).
|
||||
*/
|
||||
void signalUnBindAll(const std::shared_ptr<void>& _sharedPtr);
|
||||
void signalUnConnect(size_t _uid);
|
||||
};
|
||||
}
|
||||
|
||||
|
98
esignal/LockSharedPtrRef.h
Normal file
98
esignal/LockSharedPtrRef.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <esignal/RefCount.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
|
||||
namespace esignal {
|
||||
extern size_t s_uid;
|
||||
|
||||
template<class TYPE>
|
||||
class LockSharedPtrRef {
|
||||
public:
|
||||
RefCount<TYPE>* m_counter;
|
||||
public:
|
||||
LockSharedPtrRef(TYPE* _pointer=nullptr) :
|
||||
m_counter(nullptr) {
|
||||
if (_pointer != nullptr) {
|
||||
m_counter = new RefCount<TYPE>(_pointer);
|
||||
m_counter->inc();
|
||||
}
|
||||
}
|
||||
// copy constructor:
|
||||
LockSharedPtrRef(const LockSharedPtrRef& _obj) :
|
||||
m_counter(_obj.m_counter) {
|
||||
if (m_counter == nullptr) {
|
||||
return;
|
||||
}
|
||||
m_counter->inc();
|
||||
}
|
||||
// copy operator:
|
||||
LockSharedPtrRef& operator=(LockSharedPtrRef) = delete;
|
||||
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;
|
||||
}
|
||||
m_counter->inc();
|
||||
return *this;
|
||||
}
|
||||
// Move constructor
|
||||
LockSharedPtrRef(LockSharedPtrRef&& _obj) :
|
||||
m_counter(std::move(_obj.m_counter)) {
|
||||
|
||||
}
|
||||
// Move operator
|
||||
LockSharedPtrRef& operator=(LockSharedPtrRef&& _obj) {
|
||||
m_counter = std::move(_obj.m_counter);
|
||||
}
|
||||
~LockSharedPtrRef() {
|
||||
int64_t count = m_counter->dec();
|
||||
if (count > 0) {
|
||||
return;
|
||||
}
|
||||
delete m_counter;
|
||||
m_counter = nullptr;
|
||||
}
|
||||
void removeData() {
|
||||
if (m_counter != nullptr) {
|
||||
m_counter->remove();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
bool isAlive() {
|
||||
return m_counter != nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
76
esignal/RefCount.h
Normal file
76
esignal/RefCount.h
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
|
||||
namespace esignal {
|
||||
|
||||
template<class TYPE>
|
||||
class RefCount {
|
||||
public:
|
||||
std::mutex m_lock;
|
||||
int64_t m_count;
|
||||
TYPE* m_data;
|
||||
public:
|
||||
RefCount(TYPE* _data) :
|
||||
m_count(0),
|
||||
m_data(_data) {
|
||||
// nothing to do.
|
||||
}
|
||||
// copy constructor:
|
||||
RefCount(const RefCount&) = delete;
|
||||
// copy operator:
|
||||
RefCount& operator=(RefCount) = delete;
|
||||
RefCount& operator=(const RefCount& _obj) = delete;
|
||||
// Move constructor
|
||||
RefCount(RefCount&& _obj) = delete;
|
||||
// Move operator
|
||||
RefCount& operator=(RefCount&& _obj) = delete;
|
||||
public:
|
||||
~RefCount() {
|
||||
m_data = nullptr;
|
||||
}
|
||||
public:
|
||||
void lock() {
|
||||
m_lock.lock();
|
||||
}
|
||||
void unlock() {
|
||||
m_lock.unlock();
|
||||
}
|
||||
void inc() {
|
||||
lock();
|
||||
m_count++;
|
||||
unlock();
|
||||
}
|
||||
int64_t dec() {
|
||||
int64_t val;
|
||||
lock();
|
||||
m_count--;
|
||||
val = m_count;
|
||||
unlock();
|
||||
return val;
|
||||
}
|
||||
int64_t getCount() const {
|
||||
return m_count;
|
||||
}
|
||||
void remove() {
|
||||
lock();
|
||||
m_data = nullptr;
|
||||
unlock();
|
||||
}
|
||||
TYPE* get() {
|
||||
return m_data;
|
||||
}
|
||||
};
|
||||
}
|
249
esignal/Signal.h
249
esignal/Signal.h
@ -11,201 +11,38 @@
|
||||
#include <memory>
|
||||
#include <esignal/debug.h>
|
||||
#include <esignal/Base.h>
|
||||
#include <esignal/LockSharedPtrRef.h>
|
||||
#include <esignal/RefCount.h>
|
||||
#include <esignal/Connection.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
|
||||
namespace esignal {
|
||||
extern size_t s_uid;
|
||||
|
||||
template<class TYPE>
|
||||
class RefCount {
|
||||
public:
|
||||
std::mutex m_lock;
|
||||
int64_t m_count;
|
||||
TYPE* m_data;
|
||||
public:
|
||||
RefCount(TYPE* _data) :
|
||||
m_count(0),
|
||||
m_data(_data) {
|
||||
// nothing to do.
|
||||
}
|
||||
// copy constructor:
|
||||
RefCount(const RefCount&) = delete;
|
||||
// copy operator:
|
||||
RefCount& operator=(RefCount) = delete;
|
||||
RefCount& operator=(const RefCount& _obj) = delete;
|
||||
// Move constructor
|
||||
RefCount(RefCount&& _obj) = delete;
|
||||
// Move operator
|
||||
RefCount& operator=(RefCount&& _obj) = delete;
|
||||
public:
|
||||
~RefCount() {
|
||||
m_data = nullptr;
|
||||
}
|
||||
public:
|
||||
void lock() {
|
||||
m_lock.lock();
|
||||
}
|
||||
void unlock() {
|
||||
m_lock.unlock();
|
||||
}
|
||||
void inc() {
|
||||
lock();
|
||||
m_count++;
|
||||
unlock();
|
||||
}
|
||||
int64_t dec() {
|
||||
int64_t val;
|
||||
lock();
|
||||
m_count--;
|
||||
val = m_count;
|
||||
unlock();
|
||||
return val;
|
||||
}
|
||||
int64_t getCount() const {
|
||||
return m_count;
|
||||
}
|
||||
void remove() {
|
||||
lock();
|
||||
m_data = nullptr;
|
||||
unlock();
|
||||
}
|
||||
TYPE* get() {
|
||||
return m_data;
|
||||
}
|
||||
};
|
||||
template<class TYPE>
|
||||
class lockSharedPtrRef {
|
||||
public:
|
||||
RefCount<TYPE>* m_counter;
|
||||
public:
|
||||
lockSharedPtrRef(TYPE* _pointer) :
|
||||
m_counter(nullptr) {
|
||||
if (_pointer != nullptr) {
|
||||
m_counter = new RefCount<TYPE>(_pointer);
|
||||
m_counter->inc();
|
||||
}
|
||||
}
|
||||
// copy constructor:
|
||||
lockSharedPtrRef(const lockSharedPtrRef& _obj) :
|
||||
m_counter(_obj.m_counter) {
|
||||
if (m_counter == nullptr) {
|
||||
return;
|
||||
}
|
||||
m_counter->inc();
|
||||
}
|
||||
// copy operator:
|
||||
lockSharedPtrRef& operator=(lockSharedPtrRef) = delete;
|
||||
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;
|
||||
}
|
||||
m_counter->inc();
|
||||
return *this;
|
||||
}
|
||||
// Move constructor
|
||||
lockSharedPtrRef(lockSharedPtrRef&& _obj) :
|
||||
m_counter(std::move(_obj.m_counter)) {
|
||||
|
||||
}
|
||||
// Move operator
|
||||
lockSharedPtrRef& operator=(lockSharedPtrRef&& _obj) {
|
||||
m_counter = std::move(_obj.m_counter);
|
||||
}
|
||||
~lockSharedPtrRef() {
|
||||
int64_t count = m_counter->dec();
|
||||
if (count > 0) {
|
||||
return;
|
||||
}
|
||||
delete m_counter;
|
||||
m_counter = nullptr;
|
||||
}
|
||||
void removeData() {
|
||||
if (m_counter != nullptr) {
|
||||
m_counter->remove();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Signal<T>"
|
||||
class SignalInderection;
|
||||
class SignalBase {
|
||||
protected:
|
||||
lockSharedPtrRef<SignalBase> m_shared;
|
||||
template<class... Args>
|
||||
class Signal : public esignal::Base {
|
||||
public:
|
||||
SignalBase() :
|
||||
m_shared(this) {
|
||||
using Observer = std::function<void(const Args&...)>;
|
||||
int32_t m_callInProgress;
|
||||
public:
|
||||
Signal() :
|
||||
m_callInProgress(0) {
|
||||
|
||||
}
|
||||
// copy constructor:
|
||||
SignalBase(const SignalBase&) = delete;
|
||||
Signal(const Signal&) = delete;
|
||||
// copy operator:
|
||||
//SignalBase& operator=(SignalBase) = delete;
|
||||
//SignalBase& operator=(const SignalBase& _obj) = delete;
|
||||
Signal& operator=(Signal) = delete;
|
||||
Signal& operator=(const Signal& _obj) = delete;
|
||||
// Move constructor
|
||||
SignalBase(SignalBase&& _obj) = delete;
|
||||
Signal(Signal&& _obj) = delete;
|
||||
// Move operator
|
||||
//SignalBase& operator=(SignalBase&& _obj) = delete;
|
||||
|
||||
virtual ~SignalBase() {
|
||||
m_shared.removeData();
|
||||
}
|
||||
virtual void disconnect(std::size_t _uid) = 0;
|
||||
};
|
||||
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection(lockSharedPtrRef<SignalBase> _ref, std::size_t _id):
|
||||
m_signalRefUnique(_ref), m_uid(_id) {
|
||||
|
||||
}
|
||||
Connection(const Connection&) = delete; // not copyable
|
||||
Connection* operator=(const Connection&) = delete; // no copy operator
|
||||
Connection(Connection&&) = default; // movable
|
||||
Connection& operator=(Connection&&) = default; // movable op
|
||||
|
||||
~Connection() {
|
||||
m_signalRefUnique.disconnect(m_uid);
|
||||
m_uid = 0;
|
||||
}
|
||||
void disconnect() {
|
||||
m_signalRefUnique.disconnect(m_uid);
|
||||
m_uid = 0;
|
||||
}
|
||||
Signal& operator=(Signal&& _obj) = delete;
|
||||
private:
|
||||
lockSharedPtrRef<SignalBase> m_signalRefUnique;
|
||||
std::size_t m_uid;
|
||||
};
|
||||
|
||||
template<class... Args>
|
||||
class Signal : public SignalBase {
|
||||
public:
|
||||
using Observer = std::function<void(const Args&...)>;
|
||||
private:
|
||||
|
||||
class Executor {
|
||||
public:
|
||||
Observer m_observer;
|
||||
@ -233,7 +70,9 @@ namespace esignal {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
std::vector<std::unique_ptr<Executor>> m_executors;
|
||||
private:
|
||||
class ExecutorShared : public Executor {
|
||||
protected:
|
||||
std::weak_ptr<void> m_object;
|
||||
@ -267,24 +106,50 @@ namespace esignal {
|
||||
std::unique_ptr<Executor> executer(new Executor(std::forward<ObserverType>(observer)));
|
||||
std::size_t uid = executer->m_uid;
|
||||
m_executors.push_back(std::move(executer));
|
||||
return Connection(SignalBase::m_shared, uid);
|
||||
return Connection(Base::m_shared, uid);
|
||||
}
|
||||
template<class pointer, class Func, class... Arg>
|
||||
Connection connect(pointer* _class, Func _f, Arg... _arg) {
|
||||
template<class classType, class Func, class... Arg>
|
||||
Connection connect(classType* _class, Func _f, Arg... _arg) {
|
||||
std::unique_ptr<Executor> executer(new Executor([=]( auto&&... cargs ){
|
||||
(*_class.*_f)(cargs..., _arg... );
|
||||
}));
|
||||
std::size_t uid = executer->m_uid;
|
||||
m_executors.push_back(std::move(executer));
|
||||
return Connection(SignalBase::m_shared, uid);
|
||||
return Connection(Base::m_shared, uid);
|
||||
}
|
||||
/*
|
||||
template<class classType, class Func, class... Arg>
|
||||
void connect(const std::shared_ptr<classType>& _class, Func _f, Arg... _arg) {
|
||||
classType* tmp = _class.get();
|
||||
std::unique_ptr<ExecutorShared> executer(new ExecutorShared(_class, [=]( auto&&... cargs ){
|
||||
(*tmp.*_f)(cargs..., _arg... );
|
||||
}));
|
||||
m_executors.push_back(std::move(executer));
|
||||
}
|
||||
*/
|
||||
template<class classType, class TYPE, typename... Arg>
|
||||
void connect(const std::shared_ptr<classType>& _class, void (TYPE::*_func)(const Args&..., Arg...), Arg... _args) {
|
||||
std::shared_ptr<TYPE> obj2 = std::dynamic_pointer_cast<TYPE>(_class);
|
||||
if (obj2 == nullptr) {
|
||||
ESIGNAL_ERROR("Can not bind signal ...");
|
||||
return;
|
||||
}
|
||||
TYPE* directPointer = obj2.get();
|
||||
std::unique_ptr<ExecutorShared> executer(new ExecutorShared(_class, [=]( auto&&... cargs ){
|
||||
// TODO : Check if compilator does not use the shared ptr ...
|
||||
(*directPointer.*_func)(cargs..., _args... );
|
||||
}));
|
||||
m_executors.push_back(std::move(executer));
|
||||
}
|
||||
/*
|
||||
template<class pointer, class Func, class... Arg>
|
||||
void connect(const std::shared_ptr<pointer>& _class, Func _f, Arg... _arg) {
|
||||
void bind(const std::shared_ptr<pointer>& _class, Func _f, const Arg&... _arg) {
|
||||
std::unique_ptr<ExecutorShared> executer(new ExecutorShared(_class, [=]( auto&&... cargs ){
|
||||
(*_class.*_f)(cargs..., _arg... );
|
||||
}));
|
||||
m_executors.push_back(std::move(executer));
|
||||
}
|
||||
*/
|
||||
public:
|
||||
template< class... CallArgs>
|
||||
void emit( CallArgs&&... args) {
|
||||
@ -314,19 +179,6 @@ namespace esignal {
|
||||
}
|
||||
}
|
||||
public:
|
||||
Signal() :
|
||||
m_callInProgress(0) {
|
||||
|
||||
}
|
||||
// copy constructor:
|
||||
Signal(const Signal&) = delete;
|
||||
// copy operator:
|
||||
Signal& operator=(Signal) = delete;
|
||||
Signal& operator=(const Signal& _obj) = delete;
|
||||
// Move constructor
|
||||
Signal(Signal&& _obj) = delete;
|
||||
// Move operator
|
||||
Signal& operator=(Signal&& _obj) = delete;
|
||||
size_t size() const {
|
||||
return m_executors.size();
|
||||
}
|
||||
@ -338,9 +190,6 @@ namespace esignal {
|
||||
void clear() {
|
||||
m_executors.clear();
|
||||
}
|
||||
private:
|
||||
std::vector<std::unique_ptr<Executor>> m_executors;
|
||||
int32_t m_callInProgress;
|
||||
};
|
||||
#undef __class__
|
||||
#define __class__ nullptr
|
||||
|
@ -41,6 +41,10 @@ def create(target, module_name):
|
||||
'esignal/Interface.h',
|
||||
'esignal/Base.h',
|
||||
'esignal/Signal.h',
|
||||
'esignal/ISignal.h',
|
||||
'esignal/LockSharedPtrRef.h',
|
||||
'esignal/RefCount.h',
|
||||
'esignal/Connection.h',
|
||||
'esignal/details/Signal.hxx',
|
||||
])
|
||||
my_module.compile_version("c++", 2014)
|
||||
|
@ -61,9 +61,15 @@ class TestConnect {
|
||||
void display_values_5( int a, float b, char c, std::string _plopppp) {
|
||||
std::cout << " 5555 " << a << " " << b << " " << c << " " << _plopppp << std::endl;
|
||||
}
|
||||
void non_const(std::string _plopppp) {
|
||||
std::cout << " 987654 " << _plopppp << std::endl;
|
||||
}
|
||||
void is_const(const std::string& _plopppp) {
|
||||
std::cout << " 987654 " << _plopppp << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class TestConnectShared : public std::enable_shared_from_this<TestConnectShared>{
|
||||
class TestConnectShared : public std::enable_shared_from_this<TestConnectShared> {
|
||||
public:
|
||||
TestConnectShared() {
|
||||
|
||||
@ -74,6 +80,12 @@ class TestConnectShared : public std::enable_shared_from_this<TestConnectShared>
|
||||
void display_values_7( int a, float b, char c, std::string _plopppp) {
|
||||
std::cout << " 7777 " << a << " " << b << " " << c << " " << _plopppp << std::endl;
|
||||
}
|
||||
void non_const(std::string _plopppp) {
|
||||
std::cout << " 987654 " << _plopppp << std::endl;
|
||||
}
|
||||
void is_const(const std::string& _plopppp) {
|
||||
std::cout << " 987654 " << _plopppp << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Func, class... Arg>
|
||||
@ -98,36 +110,50 @@ TEST(test_signal_arg, checkType) {
|
||||
baseClass.emit();
|
||||
EXPECT_EQ(connectedClass->m_valueInt32, 22);
|
||||
*/
|
||||
|
||||
|
||||
esignal::Signal<std::string> signal;
|
||||
/*
|
||||
TestConnect connectedClass;
|
||||
esignal::Connection h6564 = signal.connect(connectedClass, TestConnect::non_const);
|
||||
esignal::Connection h6565 = signal.connect(connectedClass, TestConnect::is_const);
|
||||
*/
|
||||
|
||||
std::shared_ptr<TestConnectShared> connectedClassShared = std::make_shared<TestConnectShared>();
|
||||
signal.connect(connectedClassShared, &TestConnectShared::non_const);
|
||||
signal.connect(connectedClassShared, &TestConnectShared::is_const);
|
||||
|
||||
|
||||
#if 0
|
||||
esignal::Signal<int, float, char> signal;
|
||||
// ----------------------------------------------------
|
||||
auto display_values_1 = []( int a, float b, char c){
|
||||
std::cout << " 1111 " << a << " " << b << " " << c << " " << std::endl;
|
||||
};
|
||||
esignal::Connection h1 = signal.connect(display_values_1);
|
||||
esignal::Connection h1 = signal.bind(display_values_1);
|
||||
|
||||
// ----------------------------------------------------
|
||||
auto display_values_2 = []( int a, float b, char c, int w ){
|
||||
std::cout << " 2222 " << a << " " << b << " " << c << " " << w << std::endl;
|
||||
};
|
||||
esignal::Connection h2 = signal.connect( complete_args( display_values_2, 72 ) );
|
||||
esignal::Connection h2 = signal.bind( complete_args( display_values_2, 72 ) );
|
||||
|
||||
// ----------------------------------------------------
|
||||
TestConnect connectedClass;
|
||||
esignal::Connection h3 = signal.connect([&](int a, float b, char c) {
|
||||
esignal::Connection h3 = signal.bind([&](int a, float b, char c) {
|
||||
connectedClass.display_values_4(a,b,c);
|
||||
});
|
||||
/*
|
||||
signal.connect( [&](auto && ... _cargs) {
|
||||
signal.bind( [&](auto && ... _cargs) {
|
||||
connectedClass.display_values_3(_cargs);}
|
||||
);
|
||||
*/
|
||||
esignal::Connection h4 = signal.connect(&connectedClass, &TestConnect::display_values_4);
|
||||
esignal::Connection h5 = signal.connect(&connectedClass, &TestConnect::display_values_5, "coucou");
|
||||
esignal::Connection h4 = signal.bind(&connectedClass, &TestConnect::display_values_4);
|
||||
esignal::Connection h5 = signal.bind(&connectedClass, &TestConnect::display_values_5, "coucou");
|
||||
|
||||
std::shared_ptr<TestConnectShared> connectedClassShared = std::make_shared<TestConnectShared>();
|
||||
signal.connect(connectedClassShared, &TestConnectShared::display_values_6);
|
||||
signal.connect(connectedClassShared, &TestConnectShared::display_values_7, "coucou");
|
||||
signal.bind(connectedClassShared, &TestConnectShared::display_values_6);
|
||||
signal.bind(connectedClassShared, &TestConnectShared::display_values_7, "coucou");
|
||||
|
||||
|
||||
signal.emit( 5, 2.99, 'k');
|
||||
@ -138,8 +164,8 @@ TEST(test_signal_arg, checkType) {
|
||||
h4.disconnect();
|
||||
h5.disconnect();
|
||||
|
||||
//signal.connect( complete_class(&connectedClass, &TestConnect::display_values_3) );
|
||||
//signal.connect( TestConnect::display_values_3(&connectedClass) );
|
||||
//signal.bind( complete_class(&connectedClass, &TestConnect::display_values_3) );
|
||||
//signal.bind( TestConnect::display_values_3(&connectedClass) );
|
||||
|
||||
auto display_values_recursive = [&]( int a, float b, char c, int w ){
|
||||
std::cout << " 99999 " << a << " " << b << " " << c << " " << w << std::endl;
|
||||
@ -149,11 +175,15 @@ TEST(test_signal_arg, checkType) {
|
||||
}
|
||||
signal.emit(a-1, 2.66, 'l');
|
||||
};
|
||||
esignal::Connection h6 = signal.connect( complete_args( display_values_recursive, 72 ) );
|
||||
esignal::Connection h6 = signal.bind( complete_args( display_values_recursive, 72 ) );
|
||||
// ----------------------------------------------------
|
||||
|
||||
signal.emit( 5, 2.99, 'k');
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
std::cout << "========> Nes Signal " << std::endl;
|
||||
std::shared_ptr<esignal::Signal<std::string>> signalShared = std::make_shared<esignal::Signal<std::string>>();
|
||||
|
||||
@ -162,7 +192,7 @@ TEST(test_signal_arg, checkType) {
|
||||
std::cout << " 1010 " << a<< std::endl;
|
||||
std::cout << " ----------------------------------" << std::endl;
|
||||
};
|
||||
esignal::Connection h7 = signalShared->connect(display_val);
|
||||
esignal::Connection h7 = signalShared->bind(display_val);
|
||||
|
||||
std::cout << "========> Emit" << std::endl;
|
||||
signalShared->emit("coucou");
|
||||
@ -172,6 +202,9 @@ TEST(test_signal_arg, checkType) {
|
||||
|
||||
std::cout << "========> disconnect " << std::endl;
|
||||
h7.disconnect();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
std::cout << "========================================= " << std::endl;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user