Skip to content.

Sections
Personal tools
You are here: Home » ダウンロード » ThreadJack用 » doc » TJSafeEventSource

Document Actions

template <class EventType> class TJSafeEventSource: public TJEventSource<EventType>, virtual public TJSyncObject

スレッドセーフなイベントソース

継承:


Public メンバ

[more]typedef TJSafeEventListener <EventType> SafeListenerType
スレッドセーフなリスナ型

Public メソッド

[more]virtual ~TJSafeEventSource()
デストラクタ
[more]virtual void addEventListener(ListenerType* l)
イベントリスナを登録する
[more]virtual void removeEventListener(ListenerType* l)
イベントリスナを削除する.
[more]virtual void removeEventListeners()
登録されているすべての Listener を削除する
[more]virtual bool hasEventListener(const ListenerType* l) const
Listner を持っているかどうかの検査
[more]virtual void destroyEventListeners() const
登録されている Listener を delete (デストラクタ呼び出し)する
[more]virtual unsigned countEventListeners() const
現在の Listener の数を返す

Protected メソッド

[more]virtual void fireEvent(const EventType& ev)
イベントリスナにイベントを通知する
[more]virtual void fireEventRetainingLock(const EventType& ev)
イベントリスナにイベントを通知する

クラス TJEventSource:を継承している

Public メンバ

typedef TJEventListener <EventType> ListenerType

Protected メンバ

vector <ListenerType*> listeners

クラス TJSyncObject:を継承している

Public メソッド

TJSyncObject& operator=(const TJSyncObject& obj)
void wait()
bool wait(long milliseconds)
void notify()
void notifyAll()
virtual bool invariant() const

Protected メソッド

void lock()
void unlock()
int unlockTemporarily()
void restoreLock(int lockcount)

文書

スレッドセーフなイベントソース.

各種イベントのソース(発生源)の実装を支援するためのテンプレート.

TJSafeEventSource と TJSafeEventListener によるイベント伝達機構 はマルチスレッド環境における利用を想定しその安全性を高めてある.

Event, SafeListener, SafeSource の使用例を示す.

 *
 *  // アプリケーション定義のイベント型
 *  class XxxEvent {
 *       TJSafeEventSource<XxxEvent>* source;
 *       int value;
 *  public:
 *       XxxEvent(TJSafeEventSource<XxxEvent>* s, int v):
 *          source(s), value(v) {  }
 *       TJSafeEventSource<XxxEvent>* getSource() const {
 *          return source;
 *       }
 *       int getValue() const { return value; }
 *  };
 *
 *  // アプリケーション定義のイベントリスナ
 *  #include "TJSafeEventListener.h"
 *   class XxxListener : public TJSafeEventListener<XxxEvent> {
 *   public:
 *       virtual void eventHappened(const XxxEvent& ev) {
 *         TJSafeEventSource<XxxEvent>* source = ev.getSource();
 *         cout << "ev.value=" << ev.getValue() << endl;
 *         // this オブジェクトの操作は安全
 *         // ....
 *        }
 *   };
 *   // アプリケーション定義のイベントソース
 *   #include "TJEventSource.h"
 *   class XxxSource : public TJSafeEventSource<XxxEvent> {
 *       public:
 *          void foo() {
 *             // ........
 *             // イベント発生
 *             XxxEvent ev(this, 2);
 *             fireEvent(ev);  // safeEventHappened を呼び出す
 *                             // safeEventHappened は eventHappened を呼ぶ
 *          }
 *   };
 *
 *   // ソースとリスナの連結
 *   XxxSource source;
 *   XxxListener listener;
 *   source.addListener(&listener);
 *
 * 

Listener, Source の呼び出し関係は以下のようになる.

 *
 *        XxxSource                      XxxListener
 *   method() |                                 |
 * ---------> |                                 |
 *            |--+                              |
 *            |  |fireEvent()                   |
 *            |<-+                              |
 *            |                                 |
 *            |★ここで一旦                     |
 *            |全ロック解放                     |
 *            |          safeEventHappend()     |
 *            |-------------------------------->|★ここでロックを
 *            |                                 |取得する.
 *            |                                 |--+
 *            |                                 |  | eventHappend()
 *            |          method()               |<-+
 *            |<--------------------------------|
 *
 * 

[ロック方針]

一般に,SafeEventSource を継承する XxxSource と SafeEventListenerを継承する XxxListener 間では,XxxListener -> XxxSource という 方向の呼び出しが自然に起こる可能性がある.しかし,eventHappened() の呼び出しは XxxSource から XxxListenerへのコールバックとなる.

アプリケーションは,マルチスレッドのデッドロック問題を回避するために 次の原則を守ること.

(1) ソースからリスナへのイベント通知ではソース側は一切のロックを 取らずに行う.

(2) リスナからソースに対する呼び出しはソース内部で自動的にロックする.

このクラスのイベント通知処理 fireEvent() は上記(1)の原則に従って いる.さらに上記の原則(2)を守るためサブクラスのメソッドを モニタオペレーション(synchronized)とする場合は,

 *
 *     int XxxSource::method() {
 *             TJMonitor synchro__(this);  // 名前 synchro__ は任意
 *               ...
 *     }
 *
 * 

とすればよい.

【fireEvent() と fireEventRetainingLock() の違い】

(1) fireEvent() の場合

このイベントソースがロックされていれば解放してイベント通知を 実行し終了後に自動的にロックを復元する.

●利点

一般的なロック階層とは逆方向のロックを獲得しないためデッド ロックの危険性は少なくなる.

▲欠点

もしロック中に fireEvent() を呼出したとすると一時的にロック が解放されるため fireEvent() から復帰した時このイベントソー スの状態が変更されている可能性がある. これが不都合でかつ fireEvent() を選びたい場合は fireEvent() 呼出し前にスレッド資源にコピーしておく方法がある.

(2) fireEventRetainingLock() の場合

このイベントソースがロックされている場合でも解放せずにイベント 通知を実行する.

●利点

もしこのイベントソースがロックされている場合 fireEventRetainingLock() 呼出しの前後でソースオブジェクトの状態は保存される.

▲欠点

一般的なロック階層とは逆方向のロックを獲得する可能性が高いため デッドロックの危険性が大きい. fireEventRetainingLock() は内部的に既知のコードを呼出す場合で かつデッドロックの危険性がないことを保証できる場合のみと すべきである.

typedef TJSafeEventListener <EventType> SafeListenerType
スレッドセーフなリスナ型

virtual ~TJSafeEventSource()
デストラクタ. Listener のデストラクタは呼び出さないことに注意.

参照 :
destroyObservers()

virtual void addEventListener(ListenerType* l)
イベントリスナを登録する.

パラメータ:
l - 登録するリスナ.null なら無視

virtual void removeEventListener(ListenerType* l)
イベントリスナを削除する.
パラメータ:
l - 削除するリスナ.null なら無視

virtual void removeEventListeners()
登録されているすべての Listener を削除する. このメソッドが呼ばれた後,通知すべき Listener のリストは空になる. 各 Listener の delete (デストラクタ呼び出し)は行わない.

virtual bool hasEventListener(const ListenerType* l) const
Listner を持っているかどうかの検査.

パラメータ:
l - Listener オブジェクト

virtual void destroyEventListeners() const
登録されている Listener を delete (デストラクタ呼び出し)する.

基本的に Listener の delete はアプリケーションの責任とするが, アプリケーションが Listener 列の管理をしたくない場合,このメソッド が delete を支援する. Listener が自動変数の場合は,当然これを使用してはならない.

virtual unsigned countEventListeners() const
現在の Listener の数を返す.

返す値 :
現在の Listener の数

virtual void fireEvent(const EventType& ev)
イベントリスナにイベントを通知する.

【fireEvent() と fireEventRetainingLock() の違い】を参照のこと.

パラメータ:
ev - 通知するイベントオブジェクト

virtual void fireEventRetainingLock(const EventType& ev)
イベントリスナにイベントを通知する.

【fireEvent() と fireEventRetainingLock() の違い】を参照のこと.

パラメータ:
ev - 通知するイベントオブジェクト


子クラスは存在しません

索引(アルファベット順) HTMLクラス継承 または Java



This page was generated with the help of DOC++.