signals_slots.h
Go to the documentation of this file.
#ifndef SIGNAL_SLOT_H
#define SIGNAL_SLOT_H
#include <itpp/itexports.h>
#if (defined(_MSC_VER) && defined(ITPP_SHARED_LIB) && !(defined(itpp_EXPORTS) || defined(itpp_debug_EXPORTS)))
#ifndef ITPP_PROTOCOL_EXCLUDED
#define ITPP_PROTOCOL_EXCLUDED
#pragma message( "PROTOCOL definitions are not available for MSVC shared builds" )
#endif
#else
#include <itpp/protocol/events.h>
#include <list>
#include <iostream>
namespace itpp
{
class Base_Signal;
template<class DataType> class Signal;
template<class DataType> class Base_Slot;
template<class ObjectType, class DataType> class Slot;
template<class DataType>
class Signal
{
public:
friend class Base_Slot<DataType>;
Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = false);
// Signal(const std::string signal_name = "Unamed Signal", const bool single_shot = false, const bool enable_debug = true);
~Signal();
void connect(Base_Slot<DataType>* slot);
void disconnect(Base_Slot<DataType>* slot = NULL);
// Base_Event* arm(const Ttype delta_time, DataType signal); // Signal will trigger in 'delta_time' time units carrying data signal.
Base_Event* operator()(DataType signal, const Ttype delta_time = 0);
void cancel();
void set_name(const std::string &signal_name);
void set_debug(const bool enable_debug = true);
void trigger(DataType u);
protected:
typedef typename std::list<Base_Slot<DataType>*, std::allocator< Base_Slot<DataType>* > >::iterator Base_Slot_Iterator;
void _disconnect(Base_Slot<DataType>* slot);
std::list<Base_Slot<DataType>*, std::allocator<Base_Slot<DataType>* > > connected_slots;
std::string name;
private:
bool armed;
bool debug;
bool single;
Data_Event<Signal, DataType> *e;
};
template<class DataType>
class Base_Slot
{
public:
friend class Signal<DataType>;
Base_Slot(const std::string slot_name = "Unamed Base_Slot");
virtual ~Base_Slot();
void set_name(const std::string &slot_name);
virtual void operator()(DataType signal) = 0;
protected:
// virtual void exec(DataType signal) = 0;
typedef typename std::list<Signal<DataType>*, std::allocator< Signal<DataType>* > >::iterator Signal_Iterator;
std::string name;
void _connect(Signal<DataType>* signal);
void _disconnect(Signal<DataType>* signal);
std::list<Signal<DataType>*, std::allocator<Signal<DataType>* > > connected_signals;
};
template<class ObjectType, class DataType>
class Slot : public Base_Slot<DataType>
{
public:
Slot(const std::string _name = "Unamed Slot");
void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u));
~Slot();
void operator()(DataType u);
//void exec(DataType signal);
private:
ObjectType *po;
void(ObjectType::*pm)(DataType signal);
};
template<class ObjectType, class DataType>
class ATimer
{
public:
ATimer(const std::string Name = "Unamed ATimer") {
time_out_signal = new Signal<DataType>(Name, true);
time_out_slot = new Slot<ObjectType, DataType>(Name);
time_out_signal->connect(time_out_slot);
set_name(Name);
}
void forward(ObjectType *po, void(ObjectType::*pm)(DataType u)) { time_out_slot->forward(po, pm); }
void set(DataType u, const Ttype delta_t) {
time_out_signal->operator()(u, delta_t);
}
void cancel() { time_out_signal->cancel(); }
void set_name(const std::string Name) {
name = Name;
time_out_signal->set_name(name);
time_out_slot->set_name(name);
}
protected:
std::string name;
private:
Signal<DataType> *time_out_signal;
Slot<ObjectType, DataType> *time_out_slot;
};
template <class THandler>
class TTimer
{
public:
TTimer(THandler & handler, void (THandler::*handlerFunction)(Ttype time)) :
signal("timer_signal", true) {
fPending = false;
fExpirationTime = 0;
registered_handler = &handler;
registered_handler_function = handlerFunction;
slot.forward(this, &TTimer<THandler>::HandleProcessEvent);
slot.set_name("timer_slot");
signal.set_debug(false);
signal.connect(&slot);
}
virtual ~TTimer() {
if (fPending)
signal.cancel();
}
void Set(Ttype time, bool relative = true) {
if (fPending)
signal.cancel();
fPending = true;
double current_time = Event_Queue::now();
double delta_time;
if (relative) {
fExpirationTime = current_time + time;
delta_time = time;
}
else {
fExpirationTime = time;
delta_time = time - current_time;
}
signal(fExpirationTime, delta_time);
}
void Reset() {
if (fPending) {
signal.cancel();
fPending = false; // TODO: Added this myself. Didn't work otherwise.
}
}
Ttype ExpirationTime() const {
it_assert(fPending, "TTimer<>::ExpirationTime: timer not set");
return fExpirationTime;
}
bool IsPending() const { return fPending; }
protected:
virtual void HandleProcessEvent(Ttype currentTime) {
fPending = false;
(*registered_handler.*registered_handler_function)(currentTime);
}
virtual void HandleCancelEvent(Ttype) {
if (fPending)
signal.cancel();
fPending = false;
}
bool fPending;
Ttype fExpirationTime;
private:
THandler *registered_handler;
void(THandler::*registered_handler_function)(Ttype expiry_time);
Signal<double> signal; // Used internally
Slot<TTimer, double> slot; // Used internally
};
// -----------------------------------------------------------------------------------------------
template<class DataType>
Signal<DataType>::Signal(const std::string signal_name, const bool single_shot, const bool enable_debug)
{
armed = false;
e = NULL;
single = single_shot;
set_name(signal_name);
set_debug(enable_debug);
}
template<class DataType>
Signal<DataType>::~Signal()
{
Base_Slot_Iterator
begin = connected_slots.begin(),
end = connected_slots.end(),
i;
for (i = begin; i != end; i++)
(*i)->_disconnect(this);
connected_slots.clear();
if (e != NULL) // Cancel a possibly pending event since we are about to die!
e->cancel();
}
template<class DataType>
void Signal<DataType>::set_name(const std::string &signal_name)
{
name = signal_name;
}
template<class DataType>
void Signal<DataType>::set_debug(const bool enable_debug)
{
debug = enable_debug;
}
template<class DataType>
void Signal<DataType>::connect(Base_Slot<DataType>* slot)
{
Base_Slot_Iterator
begin = connected_slots.begin(),
end = connected_slots.end(),
i;
bool is_already_connected = false;
for (i = begin; i != end; i++)
if ((*i) == slot)
is_already_connected = true;
if (!is_already_connected) { // Multiple connections is meaningless.
connected_slots.push_back(slot);
slot->_connect(this); // Needed if a connected slot is deleted during run time.
}
else {
std::cout << "Signal '" << name << "' and Slot '" << slot->name << "' are already connected. Multiple connections have no effect!" << std::endl;
}
}
template<class DataType>
void Signal<DataType>::disconnect(Base_Slot<DataType>* slot)
{
Base_Slot_Iterator
begin = connected_slots.begin(),
end = connected_slots.end(),
i;
for (i = begin; i != end; i++)
if ((*i) == slot) {
(*i)->_disconnect(this);
connected_slots.erase(i);
break;
}
}
template<class DataType>
Base_Event* Signal<DataType>::operator()(DataType signal, const Ttype delta_time)
{
// Signal will trigger in 'delta_time' time units.
if (single) { // We are operating in single-shot mode.
if (armed) { // Cancel and schedule again with the new 'delta_time'.
if (debug)
std::cout << "Warning: Changing time for Signal '" << name << "'." << std::endl;
cancel();
operator()(signal, delta_time);
}
else {
e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
armed = true;
Event_Queue::add(e);
}
}
else { // Continious mode (cancel() has no effect).
e = new Data_Event<Signal, DataType>(this, &Signal<DataType>::trigger, signal, delta_time);
armed = true;
Event_Queue::add(e);
}
return e;
}
template<class DataType>
void Signal<DataType>::cancel()
{
if (armed && single) {
e->cancel();
e = NULL;
armed = false;
}
}
template<class DataType>
void Signal<DataType>::trigger(DataType u)
{
armed = false;
e = NULL;
Base_Slot_Iterator
begin = connected_slots.begin(),
end = connected_slots.end(),
i;
for (i = begin; i != end; i++) { // Execute all the functions of the connected slots.
if (debug)
std::cout << "Time = " << Event_Queue::now() << ". Signal '" << name << "' was sent to Slot '" << (*i)->name << "'." << std::endl;
(*i)->operator()(u);
}
}
template<class DataType>
void Signal<DataType>::_disconnect(Base_Slot<DataType>* slot)
{
Base_Slot_Iterator
begin = connected_slots.begin(),
end = connected_slots.end(),
i;
for (i = begin; i != end; i++)
if ((*i) == slot) {
connected_slots.erase(i);
break;
}
}
template<class DataType>
Base_Slot<DataType>::Base_Slot(const std::string slot_name)
{
set_name(slot_name);
}
template<class DataType>
void Base_Slot<DataType>::set_name(const std::string &slot_name)
{
name = slot_name;
}
template<class DataType>
Base_Slot<DataType>::~Base_Slot()
{ // Notify all signals connect that we are being deleted ...
Signal_Iterator
begin = connected_signals.begin(),
end = connected_signals.end(),
i;
for (i = begin; i != end; i++)
(*i)->_disconnect(this);
connected_signals.clear();
}
template<class DataType>
void Base_Slot<DataType>::_connect(Signal<DataType>* signal)
{ // A signal is being connected to us.
connected_signals.push_back(signal);
}
template<class DataType>
void Base_Slot<DataType>::_disconnect(Signal<DataType>* signal)
{ // A signal is being disconnected from us.
Signal_Iterator
begin = connected_signals.begin(),
end = connected_signals.end(),
i;
for (i = begin; i != end; i++)
if ((*i) == signal) {
connected_signals.erase(i);
break;
}
}
template<class ObjectType, class DataType>
Slot<ObjectType, DataType>::Slot(const std::string slot_name) : Base_Slot<DataType>(slot_name)
{
pm = NULL;
po = NULL;
}
template<class ObjectType, class DataType>
Slot<ObjectType, DataType>::~Slot() {}
template<class ObjectType, class DataType>
void Slot<ObjectType, DataType>::forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
{
pm = object_function_pointer;
po = object_pointer;
}
// template<class ObjectType, class DataType>
// void Slot<ObjectType, DataType>::exec(DataType signal){
// if(pm&&po)
// (*po.*pm)(signal);
// }
template<class ObjectType, class DataType>
void Slot<ObjectType, DataType>::operator()(DataType signal)
{
if (pm&&po)
(*po.*pm)(signal);
}
} // namespace itpp
#endif
#endif // #ifndef SIGNAL_SLOT_H
itpp::Array
General array class.
Definition array.h:105
itpp::Array::operator()
T & operator()(int i)
Get the i element.
Definition array.h:290
itpp::Base_Event
Base Event Class.
Definition events.h:69
itpp::Base_Slot
Base Slot class.
Definition signals_slots.h:185
itpp::Base_Slot::_connect
void _connect(Signal< DataType > *signal)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:566
itpp::Base_Slot::operator()
virtual void operator()(DataType signal)=0
ADD DOCUMENTATION HERE.
itpp::Base_Slot::connected_signals
std::list< Signal< DataType > *, std::allocator< Signal< DataType > * > > connected_signals
ADD DOCUMENTATION HERE.
Definition signals_slots.h:212
itpp::Base_Slot::Base_Slot
Base_Slot(const std::string slot_name="Unamed Base_Slot")
Default Constructor.
Definition signals_slots.h:539
itpp::Base_Slot::name
std::string name
ADD DOCUMENTATION HERE.
Definition signals_slots.h:206
itpp::Base_Slot::~Base_Slot
virtual ~Base_Slot()
Desctuctor.
Definition signals_slots.h:551
itpp::Base_Slot::Signal_Iterator
std::list< Signal< DataType > *, std::allocator< Signal< DataType > * > >::iterator Signal_Iterator
ADD DOCUMENTATION HERE.
Definition signals_slots.h:204
itpp::Base_Slot::set_name
void set_name(const std::string &slot_name)
set slot name
Definition signals_slots.h:545
itpp::Base_Slot::_disconnect
void _disconnect(Signal< DataType > *signal)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:572
itpp::Event_Queue::add
static void add(Base_Event *e)
Add event to Queue.
Definition events.cpp:45
itpp::Event_Queue::now
static Ttype now()
Return current time.
Definition events.h:139
itpp::Name
Automatic naming when saving.
Definition itfile.h:429
itpp::Signal
Signals and slots.
Definition signals_slots.h:125
itpp::Signal::set_name
void set_name(const std::string &signal_name)
set name of signal
Definition signals_slots.h:419
itpp::Signal::name
std::string name
ADD DOCUMENTATION HERE.
Definition signals_slots.h:169
itpp::Signal::connected_slots
std::list< Base_Slot< DataType > *, std::allocator< Base_Slot< DataType > * > > connected_slots
ADD DOCUMENTATION HERE.
Definition signals_slots.h:167
itpp::Signal::connect
void connect(Base_Slot< DataType > *slot)
Connect a slot to the signal.
Definition signals_slots.h:431
itpp::Signal::cancel
void cancel()
cancel signal
Definition signals_slots.h:495
itpp::Signal::Signal
Signal(const std::string signal_name="Unamed Signal", const bool single_shot=false, const bool enable_debug=false)
Default constructor.
Definition signals_slots.h:392
itpp::Signal::set_debug
void set_debug(const bool enable_debug=true)
Set debug mode. If true all signals are printed to stdout.
Definition signals_slots.h:425
itpp::Signal::~Signal
~Signal()
Destructor.
Definition signals_slots.h:402
itpp::Signal::operator()
Base_Event * operator()(DataType signal, const Ttype delta_time=0)
Issue a signal.
Definition signals_slots.h:470
itpp::Signal::Base_Slot_Iterator
std::list< Base_Slot< DataType > *, std::allocator< Base_Slot< DataType > * > >::iterator Base_Slot_Iterator
ADD DOCUMENTATION HERE.
Definition signals_slots.h:163
itpp::Signal::disconnect
void disconnect(Base_Slot< DataType > *slot=NULL)
Disconnect the slot from the signal.
Definition signals_slots.h:454
itpp::Signal::_disconnect
void _disconnect(Base_Slot< DataType > *slot)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:523
itpp::Signal::trigger
void trigger(DataType u)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:506
itpp::Slot
Slot Class.
Definition signals_slots.h:221
itpp::Slot::~Slot
~Slot()
Destructor.
Definition signals_slots.h:595
itpp::Slot::operator()
void operator()(DataType u)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:611
itpp::Slot::forward
void forward(ObjectType *object_pointer, void(ObjectType::*object_function_pointer)(DataType u))
ADD DOCUMENTATION HERE.
Definition signals_slots.h:598
itpp::Slot::Slot
Slot(const std::string _name="Unamed Slot")
Default constructor.
Definition signals_slots.h:588
itpp::TTimer
Definition signals_slots.h:297
itpp::TTimer::IsPending
bool IsPending() const
ADD DOCUMENTATION HERE.
Definition signals_slots.h:354
itpp::TTimer::fExpirationTime
Ttype fExpirationTime
ADD DOCUMENTATION HERE.
Definition signals_slots.h:374
itpp::TTimer::~TTimer
virtual ~TTimer()
Destructor.
Definition signals_slots.h:315
itpp::TTimer::Set
void Set(Ttype time, bool relative=true)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:321
itpp::TTimer::ExpirationTime
Ttype ExpirationTime() const
ADD DOCUMENTATION HERE.
Definition signals_slots.h:348
itpp::TTimer::TTimer
TTimer(THandler &handler, void(THandler::*handlerFunction)(Ttype time))
Default constructor.
Definition signals_slots.h:300
itpp::TTimer::Reset
void Reset()
ADD DOCUMENTATION HERE.
Definition signals_slots.h:340
itpp::TTimer::fPending
bool fPending
Flag denoting if timer is set.
Definition signals_slots.h:372
itpp::TTimer::HandleProcessEvent
virtual void HandleProcessEvent(Ttype currentTime)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:358
itpp::TTimer::HandleCancelEvent
virtual void HandleCancelEvent(Ttype)
ADD DOCUMENTATION HERE.
Definition signals_slots.h:364
events.h
Definitions of an event-based simulation class.
it_assert
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
itpp
itpp namespace
Definition itmex.h:37
itpp::Ttype
double Ttype
64-bit floating point time
Definition events.h:54

Generated on Mon Jun 10 2024 11:49:24 for IT++ by Doxygen 1.9.8