1 #ifndef JLE_SIGNAL_SLOT_H 2 #define JLE_SIGNAL_SLOT_H 11 #include "core/basic_types.hpp" 12 #include "core/shared_ptr.hpp" 17 #define JLE_CONNECT_METHOD(__SIGNAL__, __INSTANCE__, __METHOD_NAME__) \ 18 (__SIGNAL__).connect(&__INSTANCE__, &std::remove_reference<decltype(__INSTANCE__)>::type::__METHOD_NAME__); 20 #define JLE_CONNECT_THIS(__SIGNAL__, __METHOD_NAME__) JLE_CONNECT_METHOD(__SIGNAL__, *this, __METHOD_NAME__) 29 const int SIGNAL_SLOT_MAX_DEEP_EMIT = 20;
45 base_connection() : disconnected(false) {};
46 base_connection(
const base_connection&)=
delete;
47 base_connection(base_connection&&)=
default;
48 base_connection& operator=(
const base_connection&)=
delete;
49 base_connection& operator=(base_connection&&)=
default;
51 virtual ~base_connection(){};
52 virtual bool isSame(base_connection*)= 0;
54 void disconnect(
void) {
58 bool is_disconnected(
void)
const {
return disconnected; };
88 std::list<jle::weak_ptr<internal::base_connection>> list_connections;
101 list_connections.push_back(pconnection);
105 auto it_connection = list_connections.begin();
106 while(it_connection != list_connections.end())
110 if ( it_connection->expired() ) {
111 it_connection = list_connections.erase(it_connection);
114 auto sp_it = it_connection->lock();
116 if ( sp_it->is_disconnected()) {
117 it_connection = list_connections.erase(it_connection);
119 else if ( sp_it->isSame(connection.get()) ) {
121 it_connection = list_connections.erase(it_connection);
132 auto it_connection = list_connections.begin();
133 while(it_connection != list_connections.end())
135 if ( it_connection->expired() ) {
136 it_connection = list_connections.erase(it_connection);
139 it_connection->lock()->disconnect();
143 std::cerr << __PRETTY_FUNCTION__ <<
"(" << __FILE__ <<
":" << __LINE__ <<
")" <<
"exception on destructor" << std::endl;
154 template<
typename... Args>
155 class base_connectionParam
156 :
public base_connection
160 base_connectionParam() : base_connection() {};
162 virtual ~base_connectionParam(){};
164 virtual void emit(Args...)=0;
174 template<
typename TReceiver,
typename... Args>
176 :
public base_connectionParam<Args...>
178 TReceiver* pt2object;
179 void (TReceiver::*fpt)(Args...);
183 connection(TReceiver* _pt2Object,
void (TReceiver::*_fpt)(Args...))
184 : pt2object(_pt2Object),
188 void emit(Args... args){
189 (*pt2object.*fpt)(args...);
194 TReceiver* get_receiver(
void) {
197 void (TReceiver::*get_func_pointer(
void)) (Args...) {
201 bool isSame(base_connection* pbc)
203 connection<TReceiver, Args...>* pc =
dynamic_cast<connection<TReceiver, Args...
>* > (pbc);
231 template <
typename... Args>
235 int processing_emit{0};
236 std::list<
jle::shared_ptr<internal::base_connectionParam<Args...> > > connections;
239 std::list< std::tuple<void (*)(Args...),
bool> > functConnections;
252 if (processing_emit>0)
253 throw std::runtime_error(
"~signal<> on emit");
256 std::cerr << __PRETTY_FUNCTION__ <<
"(" << __FILE__ <<
":" << __LINE__ <<
")" <<
"exception on destructor" << std::endl;
267 template<
typename TReceiver>
268 void connect(TReceiver* receiver,
void (TReceiver::*fpt)(Args...)) {
269 if(connections.size()%5==0)
271 auto it2ptrbase_connection = connections.begin();
272 while(it2ptrbase_connection != connections.end())
274 if ((*it2ptrbase_connection)->is_disconnected() ==
true)
276 if (processing_emit==0)
278 it2ptrbase_connection = connections.erase(it2ptrbase_connection);
282 ++it2ptrbase_connection;
288 pbc (
new internal::connection<TReceiver, Args...>(receiver, fpt));
289 connections.push_back(pbc);
299 template<
typename TReceiver>
300 bool disconnect(TReceiver* receiver,
void (TReceiver::*fpt)(Args...)) {
301 auto it2ptrbase_connection = connections.begin();
302 while(it2ptrbase_connection != connections.end())
304 internal::connection<TReceiver>* pconnection =
dynamic_cast<internal::connection<TReceiver>*
> (it2ptrbase_connection->get());
308 pconnection->get_receiver() == receiver
310 pconnection->get_func_pointer() == fpt
312 (*it2ptrbase_connection)->is_disconnected() ==
false 315 receiver->un_internal_register_connection(
320 if (processing_emit>0)
321 (*it2ptrbase_connection)->disconnect();
324 connections.erase(it2ptrbase_connection);
328 ++it2ptrbase_connection;
340 for(
auto&& it2ptrbase_connection : connections)
342 if ( it2ptrbase_connection->is_disconnected() ==
false) {
345 if (processing_emit>0)
346 it2ptrbase_connection->disconnect();
351 if (processing_emit>0)
353 for(
auto itconnection2funct : functConnections)
355 std::get<1>(itconnection2funct) =
false;
360 functConnections.clear();
373 return emit(args...);
390 if (processing_emit>jle::SIGNAL_SLOT_MAX_DEEP_EMIT)
391 throw std::runtime_error(
"too deep recursion on emit");
393 auto itconnection = connections.begin();
394 while(itconnection != connections.end())
398 if ( (*itconnection)->is_disconnected() ==
false) {
399 (*itconnection)->emit(args...);
404 itconnection = connections.erase(itconnection);
408 std::cerr <<
"error on signal::emit()" << std::endl;
414 auto itconnection2funct = functConnections.begin();
415 while(itconnection2funct != functConnections.end())
418 if (std::get<1>(*itconnection2funct))
420 (std::get<0>(*itconnection2funct))(args...);
422 ++itconnection2funct;
426 itconnection2funct = functConnections.erase(itconnection2funct);
429 std::cerr <<
"error on signal::emit()" << std::endl;
453 template<
typename TReceiver>
454 void connect(TReceiver* receiver) {
462 void connect(
void (*pt2Function)(Args...) ) {
463 functConnections.push_back( std::make_tuple(pt2Function,
true));
470 auto itconnection2funct = functConnections.begin();
471 while(itconnection2funct != functConnections.end())
473 if (pt2Function == std::get<0>(*itconnection2funct)) {
474 if(processing_emit>0)
475 std::get<1>(*itconnection2funct) =
false;
478 functConnections.erase(itconnection2funct);
482 ++itconnection2funct;
495 #endif // JLE_SIGNAL_SLOT_H bool disconnect(TReceiver *receiver, void(TReceiver::*fpt)(Args...))
disconnect a signal from a method
Definition: signal_slot.hpp:300
void connect(void(*pt2Function)(Args...))
connect a signal to a function
Definition: signal_slot.hpp:462
int get_processing_emits(void) const
it will give the number of emits on scope
Definition: signal_slot.hpp:265
bool disconnect(void(*pt2Function)(Args...))
disonnect a signal from a function
Definition: signal_slot.hpp:469
void disconnect_all(void)
disconnect all signals
Definition: signal_slot.hpp:338
Any object connected to signals, has to inherit from signal_receptor.
Definition: signal_slot.hpp:87
A safe std smart pointer WRAPPER.
Definition: shared_ptr.hpp:39
signal instance to connect and emit
Definition: signal_slot.hpp:232
int emit(Args...args)
call all connected to the signal
Definition: signal_slot.hpp:385
void operator()(Args...args)
same as emit
Definition: signal_slot.hpp:448
generic namespace
Definition: alarm.cpp:12
int notify(Args...args)
same as emit
Definition: signal_slot.hpp:372