2008年07月24日

タイマーとスレッドこぼれネタなど

FPS計算とか実装方法とかがまだきっちり決まらないので
ここ数日で書いたもののボツにしていたり取りこぼしていたネタをいくつか記述した。
まず休止後のSetWaitableTimerでの復帰だが
まじめにGetLastError 関数でみたところ結果は$32が返っていた。

$32=ERROR_NOT_SUPPORTED

ということで要するに現環境では休止後からの復帰は出来ないということのようだ。
タスクマネージャーをはずしているのでタスクマネージャーでの復帰も確認できないが
とりあえず現状の環境では使えないことが分かった。

WaitableTimerがあまり使われていない理由は
WaitableTimerを発行したスレッドで待機しなくてはいけないという事が原因で
この仕様だとワーカースレッドとタイマースレッドの分離すら出来ず
一つのタイマーに一つのスレッドになってしまうということではないかと思う。
しかしWaitableTimerはイベントをアクティブにするのではなくて
APCキューに実行情報を送るという仕様なので送られたときに待機していなくても良いともいえる。
そのため最悪0秒の待機でも拾う。

メインスレッドでのメッセージループの間で長めのウェイトを入れて


SleepEx(0,true);


をはさむと実行することを確認した。
つまりSleepExは既にキューに入っている命令をするということで
気にせず使えそうだ。
キューを使った場合順序が保たれるなど設計しやすい点は良いのだが
処理落ちなどに対応する必要性も出てくる。
描画の実行もキューを使えば描いている最中に次の描画命令は発行されないが
おいついていなければキューがたまっていく。
キューのスタックの数は無いので自前で管理しないといけない。
いちいちクリティカルセクションとかでロックしてもいいのだが
「InterlockedIncrement」と「InterlockedDecrement」
という同期専用のカウンタ命令がつかえそうだ。

前記事では書かなかったが開放シーケンスは

for i:=0 to 6 do begin
if m_object[i] <> 0 then CloseHandle(m_object[i]);
end;


のような形でイベントでもタイマーでもスレッドでも作成していれば開放している。
現時点では固定長だがハンドル関連は可変長配列にしてもいいだろう。

また今回扱っていないタイマー関数にCreateTimerQueueというのがあるのだが
Win98で使えないからというのも一つの理由だがtimeSetEventやWaitableTimerと比べて
今ひとつメリットが感じられないので扱わないことにした。

最初つかえないと思ったWaitableTimerだがQueueUserAPCと組み合わせるとか
SleepEx(0,True);を入れるなどで使えないというわけではないという感じになってきたが


SleepEx(Fps_wait,True);

みたいにして計算したときにキューが入って抜けると再計算が面倒だし
絶対精度はあっても動作精度は他の部分の影響を受けるし
SetTimerの代替にするには複数タイマーを同時起動するにはオブジェクトも複数必要になる上
QueueUserAPCと組み合わせるならばむしろタイマー自体は別スレッドにしたいので
TimeSetEventで組める分にはできるだけTimeSetEventで組んで
むしろあまり精度のいらないタイミングで遅延実行用処理をするようにくんでみようと思っている。
多分実装しないが今日日のガベージコレクションはこの概念をもっと不器用に実装しているとみられる。

その他メッセージ関連としてWindowProcとpeekMessage後と両方に記述してどう拾うか見てきたのだが
基本的にアプリケーションは5FPS以上で描画されている前提なので
WindowProcではなくてpeekMessage後に直接記述した方がよさそうな関数としては

$F:ValidateRect(App_Window, 0 );
//WM_PAINT
$200..$20C:OnMouse(byte(App_Message.message),App_Message.wparam,App_Message.lparam);
//WM_MOUSE..
$219:OnDevChange(App_Message.wparam,App_Message.lparam);
//WM_DEVICECHANGE
あたりだけでは無いかと思う。
マウスについてはDirectInputにするか否かという問題もあるので
WindowProcと違う結果が得られるという点で必須なのはWM_DEVICECHANGEだけともいえる。
ちなみにWM_TIMERを入れる場合も外の方が良い。

ようするにUIスレッドは隙間なくいろいろ働かせるか
あるいはメッセージ処理以外はタイマーも含めて別スレッドにするか
最終的なものでなくてもいいから今までのテストにもとずいて数パターン作り先に進みたいと思う。
キューを使うということ自体排他処理の実装の一つなわけだが
クリティカルポイントやミューテックスとセマフォ、優先順位などはさし当たって必要ないので
今やったほうが良いかもしれないジャンルだが必然性が出るまでは触れないことにした。


posted by Xo_ox at 23:00| Comment(0) | Win出直し | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。