[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:### 全スレッド終了 ###
--------------------------------------------
 上の例は、多少時間的な数値や前後がおかしいですが、この裏で大量の
デバックトレースが動いているので、ずれています。