UWSC|タイムアウト関数

ポク太郎です。

UWSCは主に非同期プログラミング用てことで多少ビビっております。

頻繁に行うであろうタイムアウト判定の機能をスッキリと作り上げておきます。

色んなタイプを作成し悪戦苦闘していますが、結局、本ページで行う“モジュールを使用したある程度決め打ち”の機能が一番楽と結論しました。


タイムアウト関数(作り直し)

専用のグローバル変数、内包関数を2つ含むので“モジュール”を使用します。詳しくは関数とモジュールの書き方と使用法【使い方まとめ】

MODULE to
// 呼び出し側ソース(カウンタIDは0~99まで)
// to.clr(カウンタID)
// while (to.cnt(カウンタID,タイムアウト時間[秒])=0)
// wend
PUBLIC start[99]//それぞれの開始時刻
PUBLIC intime[99]//それぞれの使用状況

FUNCTION clr(cid)//指定のカウンタ初期化ルーチン
if intime[cid]<>0
RESULT="ポクエラー(timeoutモジュール):使用中のカウントIDが指定されました。"
else
start[cid]=GETTIME()
intime[cid]=1
RESULT=1
endif
FEND
FUNCTION cnt(cid,sec)//タイムアウト関数
r=GETTIME()-start[cid]
if (r>=sec)//タイムアウト発生
intime[cid]=0
RESULT=1
else//まだ時間内
sleep(0.1)
RESULT=0
endif
FEND
ENDMODULE
関数プログラム説明(○⇒:成り立つ場合、×⇒:成り立たない場合)
1,28
行目
1
28
MODULE TO
ENDMODULE
タイムアウトモジュールto…100コのカウンタをあらかじめ定義してあるタイムアウト機能。
引数として渡された[秒数]だけ時間が経っていなかったら0、経っていたら1を返す。
2~5
行目
2
3
4
5
//   呼び出し側ソース(カウンタIDは0~99まで)
//      to.clr(カウンタID)
//      WHILE (to.cnt(カウンタID,タイムアウト時間[])=0)
//      WEND
呼び出し側のサンプル。
while文の直前に指定のカウントIDcidを初期化して使用。
モジュール内の内部関数を呼ぶときは、モジュール名.内部関数名(引数)で呼び出します。
6,7
行目
6
7
   PUBLIC start[99]//それぞれの開始時刻
   PUBLIC intime[99]//それぞれの使用状況
本機能で使用するグローバル変数定義。
start[]:各カウンタIDの開始時間記録
intime[]:各カウンタの使用状況記録
9,17
行目
9
17
   FUNCTION clr(cid)//指定のカウンタ初期化ルーチン
   FEND
カウンタを初期化する内部関数。
引数:cid=カウンタID
10,12,16
行目
10
12
16
         IF intime[cid]<>0
         ELSE
         ENDIF
カウンタの使用状況調査。
使用中⇒エラーメッセージ。ダブって使用させない目的。
使用中でない⇒strat[]に開始時刻、intime[]を使用中にセット。
18,27
行目
18
27
   FUNCTION cnt(cid,sec)//タイムアウト関数
   FEND
実際にタイムアウト判定を行う内部関数。
引数:cid=カウントID
引数:sec=タイムアウト時間
19
行目
19                r=GETTIME()start[cid]
このルーチンを通った際の経過時間測定。
20,23,26
行目
20
23
26
         IF (r>=sec)//タイムアウト発生
         else//まだ時間内
         ENDIF
タイムアウト発生を判定する部分。
タイムアウト発生⇒intime[]0に戻し、戻り値1を返す。
まだ時間内⇒sleepを行い時間待ちし、戻り値に0を返す。
UWSCは高速演算のためのツールでないので0.1秒の休止。が、よく見かけるのは0.01秒。お好みでどうぞ。


タイムアウトモジュール動作確認

to.clr(0)
while (to.cnt(0,10)=0)
print "待ってる"

to.clr(1)
while (to.cnt(1,3)=0)
print "待ってる内部"

to.clr(2)
while (to.cnt(2,2)=0)
print "待ってるもっと内部"+GETTIME()
wend
print "終わったもっと内部"

wend
print "終わった内部"

wend
print "終わった"
関数プログラム説明(○⇒:成り立つ場合、×⇒:成り立たない場合)
1~2,18~19
行目
1
2
18
19
to.clr(0)
WHILE (to.cnt(0,10)=0)
WEND
PRINT 終わった
一番外側のループ。
5~6,15~16
行目
5
6
15
16
   to.clr(1)
   WHILE (to.cnt(1,3)=0)
   WEND
   PRINT 終わった内部
真ん中のループ。
9~10,12~13
行目
9
10
12
13
      to.clr(2)
      WHILE (to.cnt(2,2)=0)
      WEND
      PRINT 終わったもっと内部
一番内側のループ。
11
行目
11          PRINT 待ってるもっと内部+GETTIME()
現在時刻を表示しながら待機。


確認結果は、

終わったもっと内部
終わった内部
待ってる
待ってる内部
待ってるもっと内部729121811
待ってるもっと内部729121811
待ってるもっと内部729121811
待ってるもっと内部729121811
待ってるもっと内部729121811
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121812
待ってるもっと内部729121813
終わったもっと内部
待ってる内部
待ってるもっと内部729121813
待ってるもっと内部729121813
待ってるもっと内部729121813
待ってるもっと内部729121813
待ってるもっと内部729121813
待ってるもっと内部729121813
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121814
待ってるもっと内部729121815
終わったもっと内部
終わった内部
終わった

外側のループの経過時間は内部のループがタイムアウトに至るまでの時間も全部累積されるので、外側ほど長時間のタイムアウトに設定にしないと意味がなくなります。

タイムアウトモジュール使用上の注意

上で作ったタイムアウト機能は、あらかじめカウンタを100コ定義しておき使用直前にどれを使うよと選択するもの。

当然、使用中のカウンタを再選択すると数えられないのでエラーを返していますが、メインでエラー監視しないのが本機能の特徴。

要注意は、この機能を使用したループ内に、この機能を使った関数等が無いことを意識しないといけません。

なので、メイン内は外側から0番、1番、2番、…、関数内は外側から99番、98番、97番、…など、ご自身で使い方を決めておくとよいと思います。

やはり非同期プログラミングに苦戦する方が多数いらっしゃる模様。

通常、UWSCで作られるものがどんな特徴なのかをしっかり認識するために、こちらの記事で非同期プログラミングの特徴を頭に入れるといいかも。

本記事の内容は以下でした。
○タイムアウト関数

コメント

タイトルとURLをコピーしました