|
//events.h
// events and syncs
#pragma once
namespace GE_{namespace stdx1{
/// event and sync paradign
class event_source;
class event_handler_base //wil be tha virtual base for all receivers
{
private:
typedef std::list<event_source*> lstsrc_type;
lstsrc_type lstsrc;
public:
//forwarded - see beyond
void Hook(event_source& src);
void Unhook(event_source& src);
void Unhook();
virtual ~event_handler_base() { Unhook(); }
};
class event_source
{
friend class event_handler_base;
protected:
typedef std::list<event_handler_base*> rcvlist_type;
rcvlist_type rcvlist;
public:
typedef rcvlist_type::iterator rcvptr_iterator;
struct state
{
virtual bool do_next()=0;
};
private:
//will represent the iteration state
template<class Hint>
struct state_tpl: public state
{
private:
rcvptr_iterator cur, end; //list iterators
const Hint* phint; //the "event" hint
event_source* psource; //ourself
friend class event_source;
public:
bool do_next() //recourse the event into the next receiver
{
while(cur != end)
{
//seek an appropriate receiver for the hint
event_handler<Hint>* prcv = dynamic_cast<event_handler<Hint>*>(*cur);
cur++; //prepare for the next
if(!prcv) continue;
if(prcv->on_event(*phint, this)) return true; //fires and halt if returned true
}
return false;
}
};
public:
template<class Hint>
bool fire(const Hint& _hint)
{
state_tpl<Hint> st;
st.cur = rcvlist.begin();
st.end = rcvlist.end();
st.phint = &_hint;
return st.do_next();
}
virtual ~event_source()
{
while(!rcvlist.empty())
(*rcvlist.begin())->Unhook(*this);
}
};
template<class Hint>
class event_handler: //derive as many time required for as many Hint-s you have to RefcountableW32Handle
public virtual event_handler_base
{
public:
virtual bool on_event(const Hint& _hint, event_source::state* pState) {return false;}
};
inline void event_handler_base::Hook(event_source& src)
{
if(std::find(lstsrc.begin(), lstsrc.end(), &src) != lstsrc.end()) return;
lstsrc.push_front(&src);
if(std::find(src.rcvlist.begin(), src.rcvlist.end(), this) != src.rcvlist.end()) return;
src.rcvlist.push_front(this);
}
inline void event_handler_base::Unhook(event_source& src)
{
lstsrc.remove(&src);
src.rcvlist.remove(this);
}
inline void event_handler_base::Unhook()
{
lstsrc_type::iterator i;
for(i = lstsrc.begin(); i!= lstsrc.end(); ++i)
(**i).rcvlist.remove(this);
lstsrc.clear();
}
}}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Born and living in Milan (Italy), I'm an engineer in electronics actually working in the ICT department of an important oil/gas & energy company as responsible for planning and engineering of ICT infrastructures.
Interested in programming since the '70s, today I still define architectures for the ICT, deploying dedicated specific client application for engineering purposes, working with C++, MFC, STL, and recently also C# and D.