シグナル関係 GUIGUI00_man
lib_initsignalbox0_256
- lib_init + lib_opensignalbox
- 準備中
- 参考:gg00man/lib_getsig
lib_getsig0w
- 準備中
- 参考:gg00man/lib_getsig
lib_opensignalbox
int *lib_opensignalbox(int bytes, int *signalbox, int eos, int rewind) : シグナルを扱うアプリでは、ライブラリを初期化したらできるだけ速やかにこの コマンドを実行すること。 シグナルボックスをオープンする。bytesはシグナルボックスの大きさを、 バイト単位で指定します(必ず4の倍数にすること)。あまり小さいのは頻繁にrewind(後述) しなければいけなくなるが、かといって大きすぎるのはメモリの無駄になる。 256~4096くらいの範囲で使うべきだろう。signalboxはとりあえず0にする。 eosは必ず0で、rewindは0以外の適当な数値にする。これがrewindシグナルの シグナル番号になる。この関数は(int *)型の返値を持ち、それがシグナルボックスの 先頭を指すポインタである。シグナルは全てint。シグナルボックスはこのポインタから 読んでいき、読んだらポインタをインクリメントする。そうすれば、次のシグナルが 読める。シグナル0が返されたら、シグナルが溜まっていないことを意味する。その 場合はポインタをインクリメントせずにスリープする。シグナルがくれば目覚めるので、 再度そこを読めばよい。 この調子でシグナルを処理していくと、そのうちポインタがシグナルボックスの 末尾に到達する。その場合は次のシグナルは先頭に書かれている。この判定は システム側で必要に応じてやっているため、アプリはポインタをインクリメント するごとにチェックする必要はない。システムがポインタの先頭へのまき戻しが 必要だと判断するとrewindシグナルが書き込まれる。アプリ側では、これを 受け取ったらポインタを先頭に戻す。 参考になるサンプル:movec2(introa)
lib_waitsignal
void lib_waitsignal(int opt, int signaldw, int nest) : optを1にすれば、タスクはスリープし、事実上終了する。残り2つの引数は0にする。 signaldwは、アプリがシグナルを処理したことをライブラリに知らせるためのもので、 処理したシグナルのバイト数を4で割った値を指定する。rewindシグナルだけは 例外で、rewindシグナルの直後に書かれた値の分だけlib_waitsignal()で通知 する。複数のシグナルを処理して、そのsignaldwの和を一度のlib_waitsignal()で 通知してもよい。単にsignaldwを通知するためだけにlib_waitsignal()を使う時は、 optを0する。 スリープのためにlib_waitsignal()を使うときは、この場合シグナルボックスが 空になっていなければならない。もし1つでもシグナルが残っていれば、 何度lib_waitsignal()を呼んでもスリープすることはできない。どうしても スリープしたければ、シグナルを読み進めて、とにかくシグナルボックスを 空にする。読み終えたと報告したシグナルを後から読むことは許されないので、 あとで処理したければ、読み進めるシグナルを別のバッファに転送しておく。 参考になるサンプル:movec2(introa)
シグナル定義
lib_definesignal1p0
void lib_definesignal1p0(int opt, int default_assign0, int default_assign1, struct LIB_WINDOW *default_assign2, int signal) : キー入力とシグナル番号の対応づけを行う。まず、基本的にoptは0、default_assign0 には0x100を指定する。default_assign1はキーコード、default_assign2はウィンドウを 指定する。こうすることで、指定したウィンドウがアクティブになっている時に、 指定したキーが押されると、signalで指定されたシグナルがシグナルボックスに 送られる。 default_assign1は、基本的にアスキーコードで指定する。' 'や'A'や'('など、これで たいていのキーが指定できる。しかし、カーソルキーやEnterなど、アスキーコードでは 指定できないキーもあり、それらは別にしていする。 例: 0x80 ESC 0x81 F1 0x82 F2 0x83 F3 0x84 F4 0x85 F5 0x86 F6 0x87 F7 0x88 F8 0x89 F9 0x8a F10 0x8b F11 0x8c F12 0xa0 Enter 0xa1 Backspace 0xa2 Tab 0xa4 Insert 0xa5 Delete 0xa6 Home 0xa7 End 0xa8 PageUp 0xa9 PageDown 0xac Left 0xad Right 0xae Up 0xaf Down また、 for (i = 0; i < 10; i++) lib_definesignal1p0(0, 0x100, '0' + i, win, 16 + i); などと、連続するキーコードに対して連続する番号を割り当てる場合は、optを 0以外にして表現できる。上記の例の場合、 lib_definesignal1p0(9, 0x100, '0', win, 16); と書き換えられる。optは連続して割り当てたいシグナル数から1を減じた値を指定する。 現在のバージョンのOSASKではlib_definesignal1p0()を呼び出せる回数に制限があり、 この機能を利用してlib_definesignal1p0()の呼び出し回数を減らすのがよい。 optに0、default_assign0に0x10、default_assign2に0を指定すると、 タイマーシグナル設定になる。default_assign1には対応するタイマーのslot番号 (オープン済みであること)を指定する。 参考になるサンプル: キーシグナル:movec2(introa), keytstc0(introc)[拡張キーシグナル] タイマーシグナル:dblcntc0(introb)
void lib_definesignal0p0
void lib_definesignal0p0(int opt, int default_assign0, int default_assign1, int default_assign2); シグナルの割り当て宣言が一通り終わったことをライブラリに通知する。 4つ全ての引数は必ず0にする。 参考になるサンプル:movec2(introa)
タイマー制御
lib_waitsignaltime
void lib_waitsignaltime(int opt, int signaldw, int nest, unsigned int time0, unsigned int time1, unsigned int time2) : タスクを一定時間スリープさせる。optには、0x7か0xfを指定できる。 signaldwとnestは0にする。time0~time2の設定方法は、以下。 まず、設定したい時間間隔を秒で表し、その整数部をtime1に書き込む。もし、 32bitで書ききれなければ、time2に上位32bitを入れる。つまり、最大で5千万年 くらいまでは指定できる(上位数ビットは生かされないかもしれない)。 また、秒単位では細かな制御には向かないので、小数部に2^32を乗じた値を time0に設定する。これで1ns(ナノ秒)よりも細かい単位で指定できることになる。 実際はハードウェアの都合によりこの96bitの精度が完全に生かされるとは 限らない(限界まで生かす努力はする)。 optに0xfを指定した場合、 この関数をコールした時刻から指定された時間だけ待った後にタスクは目覚める。 一方、optに0x7を指定した場合は、 既に設定されている時間基点から指定された時間だけ待った後にタスクが目覚める。 時間基点というのは、タスクが起動した時刻のことだが、lib_waitsignaltime()で スリープすると目覚めた時刻が新しい時間基点にセットされる。 厳密に時間を意識するなら、optに0xfを指定するよりは0x7を指定する方がふさわしい。 なぜなら、目覚めた直後にすぐにスリープするわけではなく、 他の処理をする時間もあるからである。0xfを指定すると徐々に誤差が累積されるが、 0x7ならそういうことはない。誤差が出る場合は、アプリケーションの問題ではない。 本来はこの関数は一定時間待つためのものではなく、時限付きシグナル待ち というもので、シグナルがくれば時刻に達していなくてもタスクはスリープから回復する。 シグナル処理をしながら時間を待つもっとも単純な方法はタイマーシグナルを 使うことである。 この時間間隔指定は、少なくとも10ミリ秒以上はあってほしい。これは何も 10ミリ秒単位であることを要請しているわけではない。11.52ミリ秒などでも かまわない。頻繁に繰り替えすことがないのなら、10ミリ秒を下回ってもよい。 将来のOSASKでは、連続して何度も10ミリ秒以下の指定をした場合、OS側で強制的に 10ミリ秒間間隔に補正される可能性がある。現在のOSASKでは、OSの動作が不安定に なるからやってはいけない。 参考になるサンプル:cntdwnc1(introa)
lib_opentimer
void lib_opentimer(int slot) : タイマーシグナルのために、タイマーをオープンする。slotには0x1c0を指定する。 これはシステムタイマーslot番号で、これをオープンするとlib_waitsignaltime()が 使えなくなる。たいていはタイマーシグナルとlib_waitsignaltime()の両方を利用する ことはないので、この使い方を知っていれば十分だろう。lib_waitsignaltime()を 再び利用可能にするには、このタイマーをクローズする必要がある。 タイマーは指定されたslotだけではなく、続く2つを合わせて計3つのslot使用する。 なお、オープン直後のタイマーは休止状態にある。 参考になるサンプル:dblcntc0(introb)
lib_closetimer
void lib_closetimer(int slot) : オープンしていたタイマーをシステムに返しスロットを開放します。 クローズ後は、そのタイマーに対する設定はできない。再度オープンしても、 古い設定は保存されていない。 タイマーをクローズする前には、タイマーを停止しておくこと。 slotはタイマーとして使っていたスロット番号を指定する。使用している3つのうち、 最初の1つを指定する。
lib_settimertime
void lib_settimertime(int opt, int slot, unsigned int time0, unsigned int time1, unsigned int time2) : タイマーの時間設定をする。slotはタイマーのslot番号を指定する。 time0~time2は、lib_waitsignaltime()のものと同じ表しかたで時間を表す。 optは0x32と0x12が使える。 (註)古いguide(たとえばguide5cやguide05など)には、optのbit2, bit3を1に できるような記述があるが、これは廃止された機能なので利用してはならない。 これらのbitは必ず0です。新しい版のOSASKではこれらの廃止された機能を利用できない。 optの0x32と0x12の違いは、lib_waitsignaltime()のoptでの0xfと0x7の違いに相当。 つまり、0x32ではtime0~time2は「現在時刻に対する」値と解釈される。 一方0x12では、「前回の設定時刻に対する」値と解釈される。 タイマーはこの関数によって待機状態に入り、一度待機状態に入ると、 シグナルを発するか、もしくはキャンセルすることによって休止状態に戻るまで 次の設定はできない。 タイマーシグナルの発生頻度も、lib_waitsignaltime()と同様に、間隔が少なくとも 10ミリ秒以上はあってほしい。これももちろん10ミリ秒単位であることを要請している わけではない。また頻繁に繰り替えすことがないのなら、10ミリ秒を 下回ることがあってもかまわない。将来のOSASKでは、連続して何度も10ミリ秒以下の 指定をした場合、OS側で強制的に10ミリ秒間間隔に補正される可能性がある。 現在のOSASKでは、OSの動作が不安定になるので、やってはいけない。 参考になるサンプル:dblcntc0(introb)
lib_settimer
void lib_settimer(int opt, int slot) : 設定したタイマーをキャンセルする(これはキャンセルであって、クローズではない)。 optには0x01を指定する。slotはタイマーのslot番号を指定する。 キャンセルすると、設定した時刻になってもシグナルを発しなくなる(休止状態)。 また、何らかの事情があってシグナルを受け取る前にタイマーの設定を変える場合は、 かならずこの関数でキャンセルしてからにすること。 もともと休止状態にあるタイマーに対し、キャンセルしてもよいが、何も起きない。 参考になるサンプル:dblcntc0(introb)
lib_settimertime2
void lib_settimertime2(int opt, int slot0, int slot1, unsigned int *time) : 2つのタイマーの間の時間差を算出します。timeはunsigned intの配列(もしくはポイ ンタ)で、最低でも3つの要素が必要です。計算された値が、timeに格納されます。 time = slot1 - slot0 time[0]が下位で、time[2]が上位です。time[1]がちょうど秒の位になります。つまり、 タイマー設定の際のいつもの単位です。なおこの時に返される値の精度については保証 しません。おそらくOSASKのバージョンによってまちまちでしょう。 参考になるサンプル:starsc0(introd)
タイマーの3つの状態
A.クローズ(オープンされていない) B.休止状態(オープンされているが、時刻がきてもシグナルを発しない) C.待機状態(時刻がくればシグナルを発する) A状態のタイマーに対してはオープンしかできない。オープンするとB状態になる。 A状態のまま設定を行ってはいけない。 B状態のタイマーに対しては各種の設定とクローズができる。設定などによって、 B状態のままだったり、A状態になったり、C状態になったりする。 C状態のタイマーに対しては時刻になってシグナルが発生するのを待つか、 キャンセルしかできない。キャンセルするとB状態になる。なお、設定時刻がきて シグナルを発した後のタイマーは自動的にB状態になっている。C状態のまま 設定を行ったり、いきなりクローズするということは絶対に行ってはならない。
Counter: 196,
today: 1,
yesterday: 1
初版日時: 2003-10-24 (金) 07:33:00
最終更新: 2009-11-17 (火) 00:00:00 (JST) (349d) by ゲスト
|
ぺージ情報 | 閲覧可 | 編集可 | |||
---|---|---|---|---|---|---|
ぺージ名 : | gg00man/signal | グループ : | すべての訪問者 | グループ : | すべての訪問者 | |
ページ作成 : | ゲスト | ユーザー : | すべての訪問者 | ユーザー : | すべての訪問者 | |
ページ別名 : | 未設定 |