2009-08-03 11 views
3

私たちはイベントタイマーを扱うAPIを持っています。このAPIは、OSコールバックを使用して、(select()を使用して)明らかにタイムアウトしたイベントを処理することを示しています。UnixのC++タイマー

APIの主張は、同様の実行順: 読めるイベント 書き込み可能なイベント タイマーイベント

これは、Timerオブジェクトへのポイントを作成しますが、作成関数に関数コールバックを渡すことによって動作します。

これらの線に沿って

何か:

Timer* theTimer = Timer::Event::create(timeInterval,&Thisclass::FunctionName); 

私はこれが働いたか不思議でしたか?
オペレーティングシステムがタイマー自体を処理していて、起動されたときに実際にコールバックを呼び出す方法は?コールバックは別々の実行スレッドで実行されますか?

コールバック関数(Thisclass :: FunctionName)の中にpthread_self()呼び出しを置くと、theTimer自体が作成されたスレッドと同じスレッドIDを持つように見えます! (非常に混乱している)

また、上記の優先度リストはどういう意味ですか?書き込み可能なイベントと読み取り可能なイベントとタイマーイベントは何ですか?

このシナリオでのselect()の使用についての説明もありがたいです。

ありがとうございます!

+2

問題のAPIのドキュメントへのリンクは参考になります。それが社内のものであれば、ソースコードを読んでください。これを実装する方法はいくつでもあります。 – bdonlan

答えて

2

これは、select(2)の周りの単純なラッパーのようです。クラスは、コールバックのリストを保持しています。私は、読み込み、書き込み、およびタイマーの期限切れのために別々のものと思います。次に、dispatchまたはwaitのようなものがあります。ファイル記述子をセットにパックし、最小タイムアウトを計算し、これらの引数を使用してselectを呼び出します。 selectが返ってくると、おそらくラッパーはread setを先に読み込み、readコールバックを呼び出し、setを書き、タイマーのいずれかが期限切れになっているかどうかを調べ、それらのコールバックを呼び出します。これはすべて、同じスレッド上、またはラッパーの実装に応じて別々のスレッド上で発生する可能性があります。

selectpollでお読みください。非常に便利です。 一般用語はIO逆多重化です。

1

おそらく、create()を呼び出すと関数ポインタがどこかに格納されます。次に、タイマーがオフになると、そのポインターで指定した機能が呼び出されます。しかし、これは標準のC++関数ではないので、実際にはドキュメントを読んだり、ソースを見て確かめなければなりません。

その他の質問については、私は優先順位リストについては言及していませんし、select()は汎用イベントマルチプレクサの一種です。

2

読み取り可能なイベントとは、ブロックすることなく特定のファイル記述子でデータを読み取ることができることを意味し、書き込み可能なイベントとは、ブロックせずに特定のファイル記述子に書き込むことができることを意味します。これらはソケットとパイプで最も頻繁に使用されます。これらの詳細については、select()マニュアルページを参照してください。

タイマーイベントは、以前に作成されたタイマーが時間切れになったことを意味します。ライブラリーがselect()またはpoll()を使用している場合、ライブラリー自体はタイマーを追跡する必要があります。これらの関数は単一のタイムアウトを受け入れるからです。ライブラリーは、最初のタイマーが期限切れになるまでの残りの時間を計算し、それをtimeoutパラメーターに使用する必要があります。もう1つの方法は、timer_create()、またはsetitimer()またはalarm()のような古い形式を使用して、シグナル経由で通知を受け取る方法です。

strace(Linux)またはtruss(Solaris)のようなツールを使用して、OSレイヤーでどのメカニズムが使用されているかを判断できます。これらのツールは、プログラムによって実際に行われているシステムコールをトレースします。

1

典型的なメインループで動作するフレームワークがありますかなり可能性が高い、メインループの駆動力は、選択呼び出しです。選択

は、あなたが読みやすいか、書き込み(またはfiledeescriptorの「例外」の場合)またはタイムアウトが発生するためになるためにファイル記述子を待つことができます。 GUIライブラリであれば、unix上のファイル記述子を使って低原始的なGUIイベントを得ることができるならば、ライブラリが非同期IOを行うためのコールバックを登録できるようになります。

このようなループでタイマーコールバックを実装するには、あなただけのタイマーのプライオリティキューを維持し、選択タイムアウトまたはファイル記述子イベントにそれらを処理します。

優先順位は、タイマー(時間がかかる)がGUIの更新をもたらし、GUIイベントハンドラーが実行される前にファイルI/Oを処理することを意味します。

ライブラリは、多かれ少なかれためのタイマーコールバック内のスレッドIDは、私はそれが信号を使用して何とか実装されていることを考えるクリエイターのスレッドと同じであるという事実を

for(;;) { 
    timeout = calculate_min_timeout(); 
    ret = select(...,timeout); //wait for a timeout event or filedescriptor events 
    if(ret > 0) { 
    process_readable_descriptors(); 
    process_writable_descriptors(); 
    } 
    process_timer_queue(); //scan through a timer priority queue and invoke callbacks 
} 
0

を行っています。信号は、イベントのコールバック呼び出したスレッドの状態が保存され、シグナルハンドラが呼び出されることをスレッドに送信され

。 したがって、シグナルハンドラが返るまで中断された作成者スレッドでハンドラが呼び出されます。

たぶん、別のスレッドが(選択を使用して、すべてのタイマーを待ち)、タイマは、それが期限切れのタイマーが作成されたスレッドにシグナルを送り、期限切れになった場合。