C ++事件系统设计 [英] C++ event system design
问题描述
- 速度
- 易于使用
- 类型安全
- 友好破坏
友好破坏我的意思是事件和用户需要管理他们的断开连接,当其中一个被破坏时:
- 事件不应该调用已被销毁的订户
- 订阅者无法取消注册已被销毁的活动。
我想知道有没有人会比我想到的更好的设计:
用户观点:
struct ClickEventArg {};
// ---------------------------------------- ---------------------------------
class Button
{
public:
事件< ClickEventArg&>点击;
void SendClick(ClickEventArg& arg)
{
Clicked(this,arg);
}
};
// ---------------------------------------- ---------------------------------
class User
{
public:
void注册(按钮*按钮)
{
button-> Clicked.Subscribe(m_suscriber,this,& User :: OnButtonClicked);
}
void OnButtonClicked(void * sender,ClickEventArg& arg)
{
std :: cout<< 按钮点击;
}
private:
EventSubscriber m_suscriber;
};
// ---------------------------------------- ---------------------------------
void Test()
{
Button * button = new Button();
用户* user = new User();
user->注册(按钮);
button-> SendClick(ClickEventArg());
删除用户;
button-> SendClick(ClickEventArg());
}
内部代码:
class EventSubscriber;
// ---------------------------------------- ---------------------------------
class BaseEvent
{
public:
virtual void UnSubscribe(EventSubscriber& subscriber)= 0;
};
// ---------------------------------------- ---------------------------------
template< class TEventArgs>
class事件:public BaseEvent
{
public:
〜Event()
{
UnSubscribeAll();
}
typedef fastdelegate :: FastDelegate2< void *,TEventArgs> EventHandler;
inline void operator()(void * sender,TEventArgs args)const
{
for(SubscriberMap :: const_iterator it = m_subscribers.begin(); it!= m_subscribers。 end(); ++ it)
it-> second(sender,args);
}
模板< class TClass,class TEventArgs>
void Subscribe(EventSubscriber& subscriber,TClass * object,void(TClass :: * methodAddress)(void * sender,TEventArgs e))
{
subscriber.Subscribe(this);
m_subscribers [& subscriber] = fastdelegate :: MakeDelegate(object,methodAddress);
}
void UnSubscribe(EventSubscriber& subscriber)
{
subscriber.UnSubscribe(this);
m_subscribers.erase(& subscriber);
}
void UnSubscribeAll()
{
for(SubscriberMap :: const_iterator it = m_subscribers.begin(); it!= m_subscribers.end(); + + it)
it-> first-> UnSubscribe(this);
m_subscribers.clear();
}
private:
typedef std :: map< EventSubscriber *,EventHandler>用户地图;
订阅者地图m_subscribers;
};
// ---------------------------------------- ---------------------------------
class EventSubscriber
{
template< ; class TEventArgs>朋友班活动;
public:
〜EventSubscriber()
{
UnSubscribeAll();
}
private:
void Subscribe(BaseEvent * e)
{
m_subscriptions.insert(e);
}
void UnSubscribe(BaseEvent * e)
{
m_subscriptions.erase(e);
}
void UnSubscribeAll()
{
EventSet copy(m_subscriptions);
(EventSet :: iterator it = copy.begin(); it!= copy.end(); ++ it)
{
(* it) - > UnSubscribe(*这个);
}
}
typedef std :: set< BaseEvent *>事件集
EventSet m_subscriptions;
};
您可能会注意到我使用了这篇文章中的快速代表 http://www.codeproject.com/KB/cpp/FastDelegate.aspx 。
友好破坏方面需要EventSubscriber类。
(否则我会使用像C#中的漂亮设计)
欢迎任何反馈。
谢谢。
使用boost::signals 或 boost :: signals2 如果你想要线程安全。
I need to use an event system in C++. I have mainly four requirements :
- Speed
- Ease of use
- Type Safety
- Friendly Destruction
By "Friendly Destruction" I mean the event and the subscriber need to manage their disconnection when one of them get destroyed :
- An event shouldn't call a subscriber that has been destroyed.
- A subscriber shouldn't be able to unregister from an event that has been destroyed.
I wonder if anyone would have a nicer design than what I came up with :
User point of view :
struct ClickEventArg {};
//-------------------------------------------------------------------------
class Button
{
public:
Event<ClickEventArg&> Clicked;
void SendClick(ClickEventArg& arg)
{
Clicked(this, arg);
}
};
//-------------------------------------------------------------------------
class User
{
public:
void Register(Button* button)
{
button->Clicked.Subscribe(m_suscriber, this, &User::OnButtonClicked);
}
void OnButtonClicked(void* sender, ClickEventArg& arg)
{
std::cout << "button clicked";
}
private:
EventSubscriber m_suscriber;
};
//-------------------------------------------------------------------------
void Test()
{
Button* button = new Button();
User* user = new User();
user->Register(button);
button->SendClick(ClickEventArg());
delete user;
button->SendClick(ClickEventArg());
}
Internal code :
class EventSubscriber;
//-------------------------------------------------------------------------
class BaseEvent
{
public:
virtual void UnSubscribe(EventSubscriber& subscriber) = 0;
};
//-------------------------------------------------------------------------
template <class TEventArgs>
class Event : public BaseEvent
{
public:
~Event()
{
UnSubscribeAll();
}
typedef fastdelegate::FastDelegate2<void*, TEventArgs> EventHandler;
inline void operator() (void* sender, TEventArgs args) const
{
for (SubscriberMap::const_iterator it = m_subscribers.begin(); it != m_subscribers.end(); ++it)
it->second(sender, args);
}
template <class TClass, class TEventArgs>
void Subscribe(EventSubscriber& subscriber, TClass* object, void (TClass::*methodAddress)(void* sender, TEventArgs e))
{
subscriber.Subscribe(this);
m_subscribers[&subscriber] = fastdelegate::MakeDelegate(object, methodAddress);
}
void UnSubscribe(EventSubscriber& subscriber)
{
subscriber.UnSubscribe(this);
m_subscribers.erase(&subscriber);
}
void UnSubscribeAll()
{
for (SubscriberMap::const_iterator it = m_subscribers.begin(); it != m_subscribers.end(); ++it)
it->first->UnSubscribe(this);
m_subscribers.clear();
}
private:
typedef std::map<EventSubscriber*, EventHandler> SubscriberMap;
SubscriberMap m_subscribers;
};
//-------------------------------------------------------------------------
class EventSubscriber
{
template <class TEventArgs> friend class Event;
public:
~EventSubscriber()
{
UnSubscribeAll();
}
private:
void Subscribe(BaseEvent* e)
{
m_subscriptions.insert(e);
}
void UnSubscribe(BaseEvent* e)
{
m_subscriptions.erase(e);
}
void UnSubscribeAll()
{
EventSet copy(m_subscriptions);
for (EventSet::iterator it = copy.begin(); it != copy.end(); ++it)
{
(*it)->UnSubscribe(*this);
}
}
typedef std::set<BaseEvent*> EventSet;
EventSet m_subscriptions;
};
You may notice I used the fast delegates from this article http://www.codeproject.com/KB/cpp/FastDelegate.aspx.
The EventSubscriber class is needed for the "Friendly Destruction" aspect. (Otherwise I would have used a prettier design like in C#)
Any feedback is welcome.
Thanks.
Use boost::signals or boost::signals2 if you want thread safety.
这篇关于C ++事件系统设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!