OpenRTM-aist-Python 1.1.2
Listener クラス

このクラスは、リスナクラスの単純な保持、管理を行うリスナホルダクラ スである。このクラスを利用するためには、テンプレートの第1引数に当 たるリスナクラス (Listenerクラス) および、このListenerHolderクラス テンプレートを継承して、実際にリスナの呼び出しを行う ListenerHolder実装クラスを実装する必要がある。 [詳解]

詳解

このクラスは、リスナクラスの単純な保持、管理を行うリスナホルダクラ スである。このクラスを利用するためには、テンプレートの第1引数に当 たるリスナクラス (Listenerクラス) および、このListenerHolderクラス テンプレートを継承して、実際にリスナの呼び出しを行う ListenerHolder実装クラスを実装する必要がある。

このクラスは、スレッドセーブを実現するため、リスナの追加と削除につ いてはミューテックスによるロックを行っている。完全にスレッドセーフ なリスナ管理を実現するためにはリスナのコールバックをコールする際に もミューテックによるロックを行う必要がある。

Listenerクラスの定義

イベント発生時にコールバックされるメンバ関数を持つ基底クラスを定義 する。コールバックのためのメンバ関数は、任意の戻り値、引数を持つも のが定義でき、通常の関数であってもよいし、operator()などのファンク タとして定義してもよい。実際には基底クラスにてこれらの関数を純粋仮 想関数として定義し、このクラスを継承して、実際のリスナクラスを実装 することになる。また、ひとつのリスナクラスに複数のコールバック関数 を定義してもよい。実際には、これらのコールバック関数を実際に呼び出 す方法に関しては、次のListenerHolder実装クラスにて詳しく定義するこ とになる。

 class MyListenerBase
 {
 public:
   // コールバック関数1: 関数呼び出し演算子によるコールバック関数
   // いわゆるファンクタのようにコールバック関数を定義する例。
   virtual void operator()(std::string strarg) = 0; // 純粋仮想関数
   // コールバックの関数シグニチャが多様である場合、このように単な
   // るメンバ関数として定義することも可能。
   virtual void onEvent0(const char* arg0) = 0;
   virtual void onEvent1(int arg0) = 0;
   virtual void onEvent2(double arg0) = 0;
   virtual void onEvent3(HogeProfile& arg0) = 0;
 };
 

ListenerHolder実装クラス

ListenerHolder実装クラスはこのLsitenerHolderクラステンプレートを継 承して、上で定義した MyListenerBase クラスの追加と削除など管理を行 い、かつ実際にコールバック関数を呼び出す部分を実装することになる。 実際にコールバックを呼び出す部分では、関数シグニチャが多種多様であっ たり、ひとつのリスナクラスが複数のコールバック関数を持つ場合がある ため、個別のリスナクラスに対応するため、この呼び出し部分が必要とな る。ListenerHolder実装クラスは、MyListenerBaseクラスと同じシグニチャ を持つメンバ関数をもち、関数内部では、ListenerHolderクラスが持つ、 m_listeners, m_mutex のこれら二つのメンバ変数を利用して、登録され たリスナオブジェクトのメンバ変数を呼び出す。

 class MyListenerHolderImpl
  : public ::RTM::util::ListenerHolder<MyListenerBase>
 {
 public:
   // 関数呼び出し演算子のコールバック関数の場合
   virtual void operator()(std::string strarg)
   {
     Gurad gurad(m_mutex);
     for (int i(0), len(m_listeners.size()); i < len; ++i)
     {
       m_listeners[i].first->operator()(strarg);
     }
   }
   virtual void onEvent0(const char* arg0)
   {
     Gurad gurad(m_mutex);
     for (int i(0), len(m_listeners.size()); i < len; ++i)
     {
       m_listeners[i].first->onEvent(arg0);
     }
   }
 };
 

リスナオブジェクトへのポインタを格納しているEntryオブジェクトは std::pair<ListenerClass, bool> として定義されており、firstが Listenerオブジェクトへのポインタ、secondが自動削除フラグである。し たがって、リスナオブジェクトへアクセスする場合にはfirstを使用する。 マルチスレッド環境で利用することが想定される場合は、Guard guard(m_mutex) によるロックを忘れずに行うこと。

ListenerHolder実装クラスの利用

実装されたMyListenerHolderImplは一例として以下のように利用する。

 // たとえばクラスメンバとして宣言
 MyListenerHolderImpl m_holder;
 // 登録、自動クリーンモードで登録、
 // オブジェクトの削除はHolderクラスに任せる
 m_holder.addListener(new MyListener0(), true); // MyListener0の
 // コールバックを呼び出す
 m_holder.operator()(strarg);
 m_holder.onEvent0("HogeHoge);
 

このクラス詳解は次のファイルから抽出されました: