サイトトップへ
OSASK.NET
  サイトトップへ       新掲示板(閉鎖済)   Wiki(凍結済)   旧掲示板(廃止済)   ニュース(廃止済)  
Page Top

lib_initsignalbox0_256

Page Top

lib_getsig0w

Page Top

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)
Page Top

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)
Page Top

シグナル定義

Page Top

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)
Page Top

void lib_definesignal0p0

void lib_definesignal0p0(int opt, int default_assign0, int default_assign1,
    int default_assign2);

シグナルの割り当て宣言が一通り終わったことをライブラリに通知する。
4つ全ての引数は必ず0にする。

参考になるサンプル:movec2(introa)
Page Top

タイマー制御

Page Top

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)
Page Top

lib_opentimer

void lib_opentimer(int slot) :

タイマーシグナルのために、タイマーをオープンする。slotには0x1c0を指定する。
これはシステムタイマーslot番号で、これをオープンするとlib_waitsignaltime()が
使えなくなる。たいていはタイマーシグナルとlib_waitsignaltime()の両方を利用する
ことはないので、この使い方を知っていれば十分だろう。lib_waitsignaltime()を
再び利用可能にするには、このタイマーをクローズする必要がある。
タイマーは指定されたslotだけではなく、続く2つを合わせて計3つのslot使用する。
なお、オープン直後のタイマーは休止状態にある。

参考になるサンプル:dblcntc0(introb)
Page Top

lib_closetimer

void lib_closetimer(int slot) :

オープンしていたタイマーをシステムに返しスロットを開放します。
クローズ後は、そのタイマーに対する設定はできない。再度オープンしても、
古い設定は保存されていない。
タイマーをクローズする前には、タイマーを停止しておくこと。
slotはタイマーとして使っていたスロット番号を指定する。使用している3つのうち、
最初の1つを指定する。
Page Top

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)
Page Top

lib_settimer

void lib_settimer(int opt, int slot) :

設定したタイマーをキャンセルする(これはキャンセルであって、クローズではない)。
optには0x01を指定する。slotはタイマーのslot番号を指定する。
キャンセルすると、設定した時刻になってもシグナルを発しなくなる(休止状態)。
また、何らかの事情があってシグナルを受け取る前にタイマーの設定を変える場合は、
かならずこの関数でキャンセルしてからにすること。
もともと休止状態にあるタイマーに対し、キャンセルしてもよいが、何も起きない。

参考になるサンプル:dblcntc0(introb)
Page Top

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)
Page Top

タイマーの3つの状態

A.クローズ(オープンされていない)
B.休止状態(オープンされているが、時刻がきてもシグナルを発しない)
C.待機状態(時刻がくればシグナルを発する)

A状態のタイマーに対してはオープンしかできない。オープンするとB状態になる。
A状態のまま設定を行ってはいけない。

B状態のタイマーに対しては各種の設定とクローズができる。設定などによって、
B状態のままだったり、A状態になったり、C状態になったりする。

C状態のタイマーに対しては時刻になってシグナルが発生するのを待つか、
キャンセルしかできない。キャンセルするとB状態になる。なお、設定時刻がきて
シグナルを発した後のタイマーは自動的にB状態になっている。C状態のまま
設定を行ったり、いきなりクローズするということは絶対に行ってはならない。
Page Top

こめんと欄

  • intro出現順のほうがいいかなあ?機能的に分類した最初の順序のほうがいいかなと思ったんですが・・・。それとdefsig0p0とdefsig1p0は逆じゃない?ご意見募集。 -- K 2003-09-21 (日) 13:57:58
  • 変更中でした…defsigは気づいたので直っています。タイマーの位置もまとめたのでどうでしょうか -- くーみん編集 2003-09-21 (日) 14:32:47
  • 違和感がなくなりました。 -- K 2003-09-21 (日) 15:20:58

一般用コメント一覧

一般用コメント欄は使用できません
トップ   凍結解除 差分 バックアップ 複製 名前変更 リロード印刷に適した表示   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ
新着

目次
メンバー一覧


最新の20件
2016-10-01 2016-09-08
  • @MenuBar.
2016-09-07 2016-09-04 2016-08-15 2015-09-23 2014-07-30 2014-07-04 2014-02-04 2013-10-26 2013-06-21 2013-06-17 2013-06-15 2013-04-02 2013-02-09 2013-02-04 2012-12-25 2012-12-01 2012-05-28 2012-03-31

トピック一覧
一般用コメント最新
新掲示板lina
2016/9/5 20:58
SandBoxゲスト
2016/9/4 12:01
RecentDeletedlina
2015/6/2 19:29
Old-OSASK-MLlina
2014/6/29 9:14
hideyosi/メールhideyosi
2014/1/6 20:17
hideyosi/募集中lina
2013/11/8 19:56

このサイトは川合秀実から委託を受けて、OSASKコミュニティによって管理・運営されています。