やりたいことは一定の無通信時間に対する処理なのですが、もう少し一般的な形で表現して
●あるイベントが一定時間発生しなかったときに特定のイベントを発火させたい
というとき、どのような書き方がスマートですか?
ごく簡単には、「あるイベント」を受け取るたびに「最終時刻」を記録しておいて1秒ごとのタイマで最終時刻と現在時刻を比較すればいいですし、まあこれでソフトウェア要件は十分満たすことが大半だと思いますが、もう少し厳密に「最後のイベント発生からきっかり○○秒後」にイベントを発火させる書き方、イディオムのようなものがあればご教示いただけませんでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
こんにちは。
ウォッチドッグ・タイマなどで良く使われますが、実装に用いるハードウェアやOSのリソースにより、その実装方法や注意点は様々ですので、あまり定型的なパターンはないように思います。
ポイントは①タイムアップした時の処理を実行する仕組みと②タイムアップとタイマリスタートがほぼ同時に発生した時にどのようにして制御するのかの2点と思います。
①が決まらないと②を検討できないのでご提示の条件だけでは、処理方針を決めることはできないです。
①を行うために定期的にポーリングする方法は、データ競合の心配がなくプログラムが単純ですので、応答が遅くて良い場合に用いています。
WindowsのSetTimer()APIのようにコールバックが同じスレッドで呼ばれるような場合は、やはりデータ競合の心配はないので比較的楽にかけますが、他の処理にかまけていると応答が遅れ、タイムアップとタイマリスタートのイベントが「同時」に処理待ちになる問題を回避できません。要件によってはどちらが先か記録する仕組みが必要になるかも知れません。
①としてコールバック関数が別スレッドで呼ばれる場合はデータ競合の心配が出てくるので注意深い設計が必要ですが、応答性能を確保できます。
どの方法も一長一短で、要件に応じて適切な方法を選択するしかないと思います。
ちなみにウォッチドッグ・タイマの場合は、一般にタイムアップでシステム・リセットで、①をハードウェアにて実装する場合が多いです。(そもそもソフトウェアの暴走対策なのでソフトウェアで実装すると効果をほとんど期待できない。)
投稿2016/03/29 07:10
総合スコア23272
0
要は、タイムアウト付きのイベント待ちですよね。そのような処理にはWindows APIのWaitForSingleObject
が真っ先に思い浮かびます。その仕組みだと「あるイベント」と「タイムアウト時間」のタイミングが重なっても処理されるのはどちらか一方ですし、タイムアウトはイベントとして処理するわけではないのでリセットとかキャンセルとかも不要です。
Windows以外では自力でそれに相当するイベント待ちの処理を実装しないといけませんが。
追記
メッセージ駆動方式はどうでしょうか。
イベントをキューに入れてシリアライズし、「あるイベント」メッセージ処理でタイマーを開始し、同時にキューにタイマーメッセージが残っていたらキャンセル(削除)する。
Windowsでは、メッセージ処理専用のウィンドウを作って、イベントをシリアライズして処理するということをよくやります。
投稿2016/03/29 07:33
編集2016/03/29 08:08総合スコア5938
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/29 08:07
2016/03/29 08:35
0
うーん。
1.イベント発生時にタイマーオブジェクトを生成、内部変数に登録(登録済みのものは停止して破棄)
2.タイマーオブジェクトでイベント発生から一定時間経過後イベント発火
3.タイマーオブジェクトに対してObserverを準備しておき、Observerがイベント発火を監視
かなぁ。
Observerパターンから逃れらぬ。。。
投稿2016/03/29 06:12
総合スコア5572
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/29 06:16
2016/03/29 06:19
2016/03/29 07:01
2016/03/29 07:05
2016/03/29 07:25
2016/03/29 07:37
0
QtのQTimerなら簡単にrestart(startがそのままrestartを兼ねる実装)できるため、イベントが起きる度にrestartし続ければ簡単に実装できると思います。ただ、この方法ですとQt依存になりますし、GUIとか全体としてQtを使っていないと難しい(つまり、Qtのイベントループ上でしか動かない)です。ただ、簡単にマルチプラットフォームで実現するなら一番良いかなと思っています。
Qt依存を無くしたいので、C++のSTLのみだけで実現しようとは考えているのですが、なかなか方法が思い浮かばないです。誰かマルチプラットフォームな方法を私にも教えて欲しいです…(別スレッドでstd::this_thread::sleep_forで眠らせる…ってやったら、stopやrestartできないですよね…)
投稿2016/03/30 08:37
編集2016/03/30 08:39総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/30 09:14
2016/03/30 09:22
0
タイマーイベントで検索するとヒットします。
「あるイベント」が発生したらフラグを立てる
タイマーイベントでそれをチェックする
フラグが立っていなければ特定のイベントを発火させる
フラグをクリアする
それを繰り返す
投稿2016/03/29 06:05
総合スコア51
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/29 06:13
2016/03/29 06:21
2016/03/29 06:30
2016/03/29 06:34
2016/03/29 06:42
2016/03/29 06:53
2016/03/30 07:46
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/29 07:28
2016/03/29 07:47
2016/03/29 07:51 編集
2016/03/29 07:56
2016/03/29 08:02