C++ 事件机制实现

http://www.cppblog.com/zhuweisky/archive/2005/09/11/193.html

 

 

 事件是面向组件开发的必要特性之一,但C++不直接支持事件,没关系,我自己实现了一个,感觉很好用,分享给大家!
   最开始打算用函数指针模拟事件,但由于C++中成员函数指针不能和void*相互强转,而且 typedef中不能含有模板,所以才不得已以接口继承实现。这样效果也不错 :)


一. 先看看事件接口定义和实现

#ifndef IEVENT_H #define IEVENT_H /* 以下各基础设施是在C++中事件机制的完整实现,事件是面向组件开发的必要特性之一。 创 作 者:sky 时 间:2005.06.22 修订时间:2005.06.22 */ #include "../Collection/SafeArrayList.h" template<class SenderType ,class ParaType> class EventPublisher ; class NullType { }; // IEventHandler 是事件处理句柄,预定事件的类从此接口继承以实现事件处理函数 template<class SenderType ,class ParaType> interface IEventHandler { public: virtual ~IEventHandler(){} private: virtual void HandleEvent(SenderType sender ,ParaType para) = 0 ; friend class EventPublisher<SenderType ,ParaType> ; }; // IEvent 事件预定方通过此接口预定事件 template<class SenderType ,class ParaType> interface IEvent { public: virtual ~IEvent(){} virtual void Register (IEventHandler<SenderType ,ParaType>* handler) = 0 ; virtual void UnRegister(IEventHandler<SenderType ,ParaType>* handler) = 0 ; }; // IEventActivator 事件发布方通过此接口触发事件 template<class SenderType ,class ParaType> interface IEventActivator { public: virtual ~IEventActivator(){} virtual void Invoke(SenderType sender ,ParaType para) = 0; virtual int HandlerCount() = 0; virtual IEventHandler<SenderType ,ParaType>* GetHandler(int index) = 0; }; // IEventPublisher 事件发布方发布事件相当于就是发布一个IEventPublisher派生类的对象 // 不过仅仅将该对象的IEvent接口发布即可。 template<class SenderType ,class ParaType> interface IEventPublisher : public IEvent<SenderType ,ParaType> ,public IEventActivator<SenderType ,ParaType> { }; // EventPublisher是IEventPublisher的默认实现 template<class SenderType ,class ParaType> class EventPublisher :public IEventPublisher<SenderType ,ParaType> { private: SafeArrayList< IEventHandler<SenderType ,ParaType> > handerList ; IEventHandler<SenderType ,ParaType>* innerHandler ; public: void Register(IEventHandler<SenderType ,ParaType>* handler) { this->handerList.Add(handler) ; } void UnRegister(IEventHandler<SenderType ,ParaType>* handler) { this->handerList.Remove(handler) ; } void Invoke(SenderType sender ,ParaType para) { int count = this->handerList.Count() ; for(int i=0 ;i<count ;i++) { IEventHandler<SenderType ,ParaType>* handler = this->handerList.GetElement(i) ; handler->HandleEvent(sender ,para) ; } } int HandlerCount() { return this->handerList.Count() ; } IEventHandler<SenderType ,ParaType>* GetHandler(int index) { return this->handerList.GetElement(index) ; } }; #endif

上面的实现是浅显易懂的,关键是要注意IEventPublisher的双重身份-- 事件发布方最好发布IEvent指针给外部,而该指针实际指向的是一个EventPublisher对象,这是为了避免外部直接调用IEventActivator接口的方法。

二. 一个定时器类Timer,演示如何发布事件。想必大家都知道定时器的用途了哦,这个Timer就像C#中的Timer类一样。

#ifndef TIMER_H #define TIMER_H /* Timer 定时器,每经过一段指定时间就触发事件 创 作 者:sky 时 间:2005.06.22 修订时间:2005.06.22 */ #include "IEvent.h" #include "Thread.h" void TimerThreadStart(void* para) ; class Timer { private: int spanInMillSecs ; volatile bool isStop ; volatile bool timerThreadDone ; public: friend void TimerThreadStart(void* para) ; IEvent<Timer* ,NullType>* TimerTicked ; Timer(int span_InMillSecs) { this->isStop = true ; this->timerThreadDone = true ; this->spanInMillSecs = span_InMillSecs ; this->TimerTicked = new EventPublisher<Timer* ,NullType> ; } ~Timer() { this->Stop() ; delete this->TimerTicked ; } void Start() { if(! this->isStop) { return ; } this->isStop = false ; Thread thread ; thread.Start(TimerThreadStart ,this) ; //unsigned int dwThreadId ; //HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0 , (unsigned int (_stdcall*)(void*))&TimerThreadStart , this, 0, &dwThreadId); } void Stop() { if( this->isStop) { return ; } this->isStop = true ; //等待工作线程退出 while(! this->timerThreadDone) { Sleep(200) ; } } private: void WorkerThread() { this->timerThreadDone = false ; while(! this->isStop) { Sleep(this->spanInMillSecs) ; if(this->isStop) { break ; } NullType nullObj ; ((EventPublisher<Timer* ,NullType>*)this->TimerTicked)->Invoke(this ,nullObj) ; } this->timerThreadDone = true ; } }; void TimerThreadStart(void* para) { Timer* timer = (Timer*)para ; timer->WorkerThread() ; } #endif

上面的示例清晰地说明了如何发布一个事件,如何在适当的时候触发事件,接下来看看如何预定事件。

三. 预定事件例子

class TimerEventExample :public IEventHandler<Timer* ,NullType> ,CriticalSection { private: Timer* timer ; public: TimerEventExample(int checkSpan) { this->timer = new Timer(checkSpan) ; this->timer->TimerTicked->Register(this) ; } ~TimerEventExample() { delete this->timer ; } private: //处理定时事件 void HandleEvent(Timer* sender ,NullType para) { cout<<"Time ticked !"<<endl ; } };

 到这里,已经将C++中的事件机制的实现及使用讲清楚了。C#提供了很多便利的基础设施来支持组件开发,而在C++中,这些基础设施需要自己动手来构建,在拥有了这些设施之后,相信使用C++进行组件开发会轻松一点。

你可能感兴趣的:(thread,C++,timer,C#,delete,Class)