プログラミングのはなし。
業務系の方は???かもしれませんが、制御系の方には当たり前の話かもしれません。
通常Windowsで定周期処理を行う場合Windowsタイマを使用します。しかしながらこのタイマは正確な割り込みを行うことができません。WindowsがイベントドリブンなOSであり、また周期の通達手段がメッセージであることが原因だと思います。Windows全体の負荷が高くなるとメッセージ処理は後回しになってしまいます。また最小分解能はWin98系が55ms、NT系が10ms程度だったと思います(Win2000以降は調べてません)。
以前、サイクルタイム10±2msの制御をWindowsで求められたことがありました。その時に使用したのがマルチメディアタイマです。Windowsタイマと決定的に異なるのは、周期の通達手段がメッセージでなく「OSからの関数コールバック」という点です。(厳密に言えばOS内部では管理用の専用スレッドが立ち上がっているであろう点も重要なポイントかもしれません)。
最近、少し手が空いたので、マルチメディアタイマをラップしてクラス化したんです。やっと本題です。コールバック関数の再入防止が機能しているかテストしようとした時のことです。
次のようなコードで再入を検知しようとしましたが、検知できませんでした。
void TMMTimer::OnTimer( void )
{
// 既に割り込み発生中ならば処理しない
if( bExist ) // <--- 成立しない
{
return ;
}
// 処理中を明示
bExist = true ;
// 時間のかかる処理
たとえばインターバル1msでコールバックが発生する場合に、コールバック中で1ms以上の処理を行えば必ず再入すると考えていたんです。しかし再入が発生することはありませんでした。最初は悩みましたが、いろいろ確認していくうちに原因が判明しました。断言された資料に当たってないので推測の域を出ませんが・・・。
OSからのコールバックはイベントキューになっている。
コールバック中にインターバル時間以上の処理を行った場合、
処理が完了した後に次のコールバックが行われる。
すなわち、再入は発生しない。という結論に到達しました。
詳しい方がいらっしゃいいましたらフォローください(汗)
Comments