[1383] マルチスレッドについて
投稿者:山
2009/07/16 00:58:48
ようやくマルチスレッドの組込みが終わりました。テストモデルは比較的
早くできたのですが、実際の組込みは多少時間がかかりました。全体的なり
ファクタリングが必要だったし。
下記プログラムのように、同じ関数を3スレッドで平行実行しています。
この言語の特徴は、なんらマルチスレッドを意識することなく、ただ関数を
書くだけでマルチで実行可能な点です。関数の入り口の書式は決まっていま
すが、そこから呼ばれているprintln()等は何も意識していません。ちなみ
にHシートのシステム変数はスレッド置きに作成され、そのスレッドが所有
権を持ちます。スレッドが100個あれば100枚のHシートができます。
この様にシートによって各種特徴やサービスがあるシートと、自由に使え
る汎用シートがあります。
システム変数は総て所有権が有り、一つのスレッドが所有者になります。
もちろん委譲したり戻したり出来ますが、一度に1つのスレッドしか所有権
を持ちません。
また、一般的なスレッドと多少性格が違い、1つのスレッドを起動すると、
初期起動実行後、メッセージ(キュー)が来るまで待ち状態で待機します。
待機時のCPU消費は0です。メッセージ駆動型のスレッドです。普通に関数
を書くだけで、いくら並列に起動されようと問題なく動きます。特別な知識
も要りません。
//-- スレッド操作関数 ----------------
#define スレ開始 thread_start
#define スレ終了待ち thread_exit_waiting
#define 終了待ち 0 // 終了を待つ
#define 終了指示待ち 1 // 終了指示を出し終了を待つ
#define 強制終了待ち 2 // 強制終了を出し終了を待つ
//-- スレ終了待ち関数の戻り値 ---------
#define 正常終了 0 // スレ正常終了
#define タイムアウト 1 // スレ終了待ちがタイムアウト
//-- スレッド終了コード --------------
#define スレッド待機 0 // スレッドはキュー待ちに
#define スレッド終了 1 // スレッド終了
#define スレッドエラー終了 2 // スレッドエラー終了
//-- キューID ------------------------
#define スレッド開始 1 // スレッド開始キューID
#define タイマ 2 // タイマキューID
#define 終了指示 3 // 終了指示キューID
//------------------------------------
#define 時間取出し get_ms_time
#define 眠る sleep
#define システム変数 sysval
#define 生成 1 // システム変数生成
//-- 組込み関数宣言 -------------------
int print(string str);
int スレ開始(string fname,int ms,int p1,string p2,string p3);
int スレ終了待ち(int sid,int type,int timeout);
int システム変数(string str,int type);
int 眠る(int time);
int 時間取出し();
//------------------------------------------------------
int main()
{
//-- 同じ関数を違う周期でマルチスレッド起動する -------
int[3] sid;
println("### スレッド起動 ###");
// 関数名, ms周期,P1, P2, P3
sid[0] = スレ開始("タイマ表示",40,6," 40ms"," で6回実行");
sid[1] = スレ開始("タイマ表示",60,5," 60ms"," で5回実行");
sid[2] = スレ開始("タイマ表示",80,4," 80ms"," で4回実行");
println(" sid[0] ="+sid[0]+" sid[1] ="+sid[1]+" sid[2] ="+sid[2]);
println("眠る前 ms=" + 時間取出し());
眠る(300); // 300ms眠る
println("眠る後 ms=" + 時間取出し());
//-- スレッドが終了するまで待つ ---------------------
int[3] rtn;
rtn[0] = スレ終了待ち(sid[0],終了待ち,10); // 10秒でタイムアウト
rtn[1] = スレ終了待ち(sid[1],終了待ち,10);
rtn[2] = スレ終了待ち(sid[2],終了待ち,10);
println(" rtn[0] ="+rtn[0]+" rtn[1] ="+rtn[1]+" rtn[2] ="+rtn[2]);
println("### 全スレッド終了 ###");
return 98;
}
//-- システム変数の定義 --------------------------------
#define カウント HAI000 // タイマのカウンタ
#define 回数 HAI001 // p1の終了回数
#define P2STR HAS000 // p2の文字列
#define P3STR HAS001 // p3の文字列
//-- 複数スレッド起動される周期タイマー処理関数 ---------
int タイマ表示(int sid, int qid,int p1, string p2, string p3)
{
string questr = " SID=" + sid + " QID=" + qid;
if(qid == スレッド開始) {
// スレッド起動時のみ時実行 --------------
println("タイマ表示スレッド開始"+questr+" 回数="+p1+p2+p3);
システム変数("HAI000-HAI001",生成);
カウント = 0;
回数 = p1;
システム変数("HAS000-HAS001",生成);
P2STR = p2;
P3STR = p3;
} elsif(qid == タイマ) {
// タイマキューにより実行 --------------
カウント++;
println("タイマ表示"+questr+" cnt="+カウント+P2STR+P3STR);
if(カウント >= 回数) {
println("タイマ表示スレッド終了" + questr);
return スレッド終了;
}
} elsif(qid == 終了指示) {
println("タイマ表示 終了指示により終了" + questr);
return スレッド終了;
} else {
println("タイマ表示スレッド エラー終了" + questr);
return スレッドエラー終了;
}
return スレッド待機;
}
//------------------------------------------------------
int println(string str)
{
print(str + "\n");
return 0;
}
//------------------------------------------------------
↓
実行結果
↓
--------------------------------------------
3:### スレッド起動 ###
3: sid[0] =1 sid[1] =2 sid[2] =3
3:タイマ表示スレッド開始 SID=1 QID=1 回数=6 40ms で6回実行
3:タイマ表示スレッド開始 SID=2 QID=1 回数=5 60ms で5回実行
3:タイマ表示スレッド開始 SID=3 QID=1 回数=4 80ms で4回実行
3:眠る前 ms=33696948
3:タイマ表示 SID=1 QID=2 cnt=1 40ms で6回実行
3:タイマ表示 SID=2 QID=2 cnt=1 60ms で5回実行
3:タイマ表示 SID=3 QID=2 cnt=1 80ms で4回実行
3:タイマ表示 SID=1 QID=2 cnt=2 40ms で6回実行
3:タイマ表示 SID=2 QID=2 cnt=2 60ms で5回実行
3:タイマ表示 SID=3 QID=2 cnt=2 80ms で4回実行
3:タイマ表示 SID=1 QID=2 cnt=3 40ms で6回実行
3:タイマ表示 SID=2 QID=2 cnt=3 60ms で5回実行
3:タイマ表示 SID=3 QID=2 cnt=3 80ms で4回実行
3:眠る後 ms=33697360
3:タイマ表示 SID=1 QID=2 cnt=4 40ms で6回実行
3:タイマ表示 SID=2 QID=2 cnt=4 60ms で5回実行
3:タイマ表示 SID=1 QID=2 cnt=5 40ms で6回実行
3:タイマ表示 SID=3 QID=2 cnt=4 80ms で4回実行
3:タイマ表示 SID=2 QID=2 cnt=5 60ms で5回実行
3:タイマ表示スレッド終了 SID=3 QID=2
3:タイマ表示スレッド終了 SID=2 QID=2
3:タイマ表示 SID=1 QID=2 cnt=6 40ms で6回実行
3:タイマ表示スレッド終了 SID=1 QID=2
3: rtn[0] =0 rtn[1] =0 rtn[2] =0
3:### 全スレッド終了 ###
--------------------------------------------
上の例は、多少時間的な数値や前後がおかしいですが、この裏で大量の
デバックトレースが動いているので、ずれています。