c++イベントバスのシンプルな実装

7041 ワード

文書ディレクトリ
  • 1. イベントバス
  • 2. 任意のタイプのパラメータ
  • 3. 登録メカニズム
  • 4. スレッド処理
  • 5. BOOSTライブラリリンク時プロンプト「libxxx」
  • が見つかりませんでした
  • 6. Multimap用法
  • 7.イベントバスの簡単な実装
  • 1.イベントバス
    マルチスレッド操作に使用し、ライブラリとライブラリの結合を低減し、実行効率を向上させます.
    2.任意のタイプのパラメータ
    可変タイプが必要な場合は、3つの可能なソリューションがあります.
  • 無制限のタイプ、例えばvoid*.この方法はタイプが安全ではないので、災害を避けるように避けるべきだ.
  • 可変タイプ、すなわち、複数のタイプのストレージおよび取得をサポートするタイプ.
  • は、文字列タイプと整数タイプとの間の変換などの変換のタイプをサポートします.

  • 解決方法:boost::Anyを使用
    boost::Anyの重要な特性は、異なるタイプのオブジェクトを標準ライブラリコンテナに格納する能力を提供することです.C++標準ライブラリが非常に必要で不足している可変データ型でもあります.
    使用法:anyは、タイプを知っている限り、その値にアクセスできます.
  • ヘッダファイル
  • テンプレート関数any_cast:
      template  ValueType any_cast(const any& operand);
      any_cast     any     。          any   。
           ValueType       ,any      bad_any_cast   。
         ,        dynamic_cast.
      
      template  const ValueType* any_cast(const any* operand);
      any_cast      ,       any    ,           const  。
         any        ValueType,         。
    
      template  ValueType* any_cast(any* operand);
      any_cast       ,        
    

  • 3.登録メカニズム
    4.スレッド処理
    boost::thread:
    class HelloWorld
    {
    public:
     	void hello(const std::string& str)
     	{
            std::cout<

    スレッドローカルストレージ:
    Boostスレッドライブラリには、スマートポインタboost::thread_specific_ptrは、ローカルストレージスレッドにアクセスします.各スレッドがこのスマートポインタのインスタンスを初めて使用する場合、その初期値はNULLなので、空であるかどうかを確認し、値を割り当てる必要があります.Boostスレッドライブラリは、ローカルストレージスレッドに保存されているデータがスレッド終了後に消去されることを保証します.
    #include 
    #include 
    #include 
    #include 
     
    boost::mutex io_mutex;
    boost::thread_specific_ptr ptr;//      
     
    struct count
    {
    	count(int id) : id(id) { }
     
    	void operator()()
    	{
    		if (ptr.get() == 0)//   
    			ptr.reset(new int(0));
     
    		for (int i = 0; i < 10; ++i)
    		{
    			(*ptr)++;
    			boost::mutex::scoped_lock lock(io_mutex);
    			std::cout << id << ": "	<< *ptr << std::endl;
    		}
    	}
     
    	int id;
    };
     
    int main(int argc, char* argv[])
    {
    	boost::thread thrd1(count(1));
    	boost::thread thrd2(count(2));
    	thrd1.join();
    	thrd2.join();
    	return 0;
    }
    

    5.BOOSTライブラリリンク時プロンプト「libxxx」が見つからない
    BOOSTライブラリをコンパイルする場合、動的ライブラリまたは静的ライブラリを生成できます.BOOSTのデフォルトでは静的ライブラリリンクが使用され、自動的にリンクできますが、動的ライブラリを使用する場合は、マクロ:BOOST_ALL_DYN_LINKを追加する必要があります.
    bjam stage –toolset=msvc-10.0–without-python 
    stagedir="D:/SDK/boost_1.60/vs2010" link=shared 
    runtime-link=shared threading=multi debug release
    

    静的ライブラリリンクBOOSTを使用することをお勧めします
    6.マルチマップの使い方
    挿入用insert(make_pair(K,V))
    「mk」をキーとするすべての値を検索
    RetRange range = _eventMap.equal_range(“mk”);
    for (constItr itr = range.first; itr != range.second; ++itr)
    {
    	...
    }
    

    削除:
    iterator  erase (const_iterator position);//         
    size_type erase (const key_type& k);//     K     
    iterator  erase (const_iterator first, const_iterator last);
    

    7.イベントバスの簡単な実現
    .h
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "SingleApp.h"
    
    
    /*   */
    class IEvent
    {
    public:
    	enum EventType{
    		type_async =0,
    		type_sync,
    	};
    
    public:
    	IEvent(const int & id, int pri=127, EventType type= type_async);
    	IEvent(const IEvent & other);
    	IEvent & operator=(const IEvent & other);
    	bool operator ==(const IEvent & other)const;
    	bool operator < (const IEvent & other)const;
    
    private:
    	int _id;
    	int _priority;
    	EventType _type;
    };
    
    
    //     
    struct IHandler
    {
    	boost::any _param;
    };
    //        
    typedef boost::function Func;
    typedef std::multimap HandlerMap;	//    
    typedef HandlerMap::const_iterator constItr;
    typedef std::pair RetRange;	//    
    
    
    /*     */
    class EventBus: public SingleApp
    {
    public:
    	EventBus(void);
    	~EventBus(void);
    
    public:
    
    	/************************************************************************/
    	/*     
    		e:    
    		Func:       , boost::bind(&X::f, this, _1)
    	*/
    	/************************************************************************/
    	void Subscribe(const IEvent & e, Func & handler);
    
    	/************************************************************************/
    	/*  Post  
    		e:  
    		IHandler:  
    	*/
    	/************************************************************************/
    	void Post(const IEvent & e, const IHandler & param);
    
    	/************************************************************************/
    	/*       
    	*/
    	/************************************************************************/
    	void UnSubscribe(const IEvent & e);
    
    private:
    	HandlerMap _eventMap;
    };
    

    .cpp
    #include "EventBus.h"
    #include 
    #include 
    
    
    IEvent::IEvent( const int & id, int pri/*=127*/, EventType type/*= type_async*/ )
    {
    	_id = id;
    	_priority = pri;
    	_type = type;
    }
    
    IEvent::IEvent( const IEvent & other )
    {
    	if (this == & other)
    	{
    		return;
    	}
    	else
    	{
    		this->_id = other._id; 
    		this->_priority = other._priority;
    		this->_type = other._type;
    	}
    }
    
    IEvent & IEvent::operator=( const IEvent & other )
    {
    	if (this == & other)
    	{
    		return *this;
    	}
    
    	this->_id = other._id; 
    	this->_priority = other._priority;
    	this->_type = other._type;
    	return *this;
    }
    
    
    bool IEvent::operator==( const IEvent & other ) const
    {
    	if (this->_id == other._id && 
    		this->_priority== other._priority &&
    		this->_type == other._type)
    	{
    		return true;
    	}
    	return false;
    }
    
    bool IEvent::operator_id < other._id )
    	{
    		return true;
    	}
    	return false;
    }
    
    EventBus::EventBus(void)
    {
    
    }
    
    EventBus::~EventBus(void)
    {
    }
    
    void EventBus::Subscribe(const IEvent & e, Func & handler )
    {
    	_eventMap.insert(std::make_pair(e,handler));
    }
    
    void EventBus::Post( const IEvent & e, const IHandler & param )
    {
    	RetRange range = _eventMap.equal_range(e);
    	for (constItr itr = range.first; itr != range.second; ++itr)
    	{
    		Func f = itr->second;
    		boost::thread thread(f, param._param);
    	}
    }
    
    void EventBus::UnSubscribe( const IEvent & e )
    {
    	_eventMap.erase(e);
    }
    

    参照先:
  • my coding.net
  • 定義
  • boost.anyは任意のタイプのストレージ
  • を実現する
  • Boostベースのスレッドセキュリティキュー
  • boostが提供するいくつかのlock-freeスキームおよびstd::atomicはロックレスキュー
  • を実現する
  • boost::threadの6つの使い方まとめ
  • スレッドローカル記憶領域
  • を理解する.
  • 毎日少しずつ進歩-Linuxのスレッドローカルストレージ(一)
  • boostスレッドローカルストレージ
  • STLのmultimap使用概要
  • http://www.cplusplus.com/reference/map/multimap/multimap/
  • イベントバス(Event Bus)知っている