読者です 読者をやめる 読者になる 読者になる

No Programming, No Life

新しいNPNLです。http://d.hatena.ne.jp/fumokmm/ から引っ越してきました。

スレッドのテスト

UWSC

v4.0からスレッドが使えるようになったようなので、
早速怪しげなサンプルでテストしてみました。

PUBLIC LOCK = FALSE		// 順位用のロック
PUBLIC THREAD_COUNT = 0	// 起動したスレッド数
PUBLIC FINISH_COUNT = 0	// 終わったスレッド数
PUBLIC WINNER = ""		// 結果
PUBLIC FINISH_X = 800	// 終端のx座標
PUBLIC DELTA = 100		// 増分

// スレッドを起動
THREAD run("スレッドA", 100)
THREAD run("スレッドB", 150)
THREAD run("スレッドC", 200)
THREAD run("スレッドD", 250)
THREAD run("スレッドE", 300)
THREAD run("スレッドF", 350)
THREAD run("スレッドG", 400)
THREAD run("スレッドH", 450)
THREAD run("スレッドI", 500)
THREAD run("スレッドJ", 550)
THREAD run("スレッドK", 600)
THREAD run("スレッドL", 650)

// 全てのスレッドが終了するまで待つ
WHILE FINISH_COUNT = 0 OR THREAD_COUNT = 0 OR FINISH_COUNT < THREAD_COUNT
	SLEEP(0.1)
WEND

// 結果を表示して終了
MSGBOX("おしまい。<#CR>" + WINNER)

// スレッド処理のプロシージャ
PROCEDURE run(msg, y)
	THREAD_COUNT = THREAD_COUNT + 1
	DIM x = 0
	// x座標がFINISH_Xになるまで繰り返し
	WHILE x < FINISH_X
		FUKIDASI(msg + "(" + x + ")", x, y)
		x = x + RANDOM(DELTA)
		SLEEP(0.2)
	WEND

	// ロックが解放されるまで待つ
	WHILE LOCK
		SLEEP(0.01)
	WEND

	// ロックして更新
	LOCK = TRUE
	FINISH_COUNT = FINISH_COUNT + 1
	WINNER = WINNER + FINISH_COUNT + "位 " + msg + "<#CR>"
	LOCK = FALSE
FEND

v4.0以降のUWSCで起動してください。
起動すると非同期でふきだしが移動しているのが見て取れます。
ちなみに

// スレッドを起動
THREAD run("スレッドA", 100)
THREAD run("スレッドB", 150)
THREAD run("スレッドC", 200)
THREAD run("スレッドD", 250)
THREAD run("スレッドE", 300)
THREAD run("スレッドF", 350)
THREAD run("スレッドG", 400)
THREAD run("スレッドH", 450)
THREAD run("スレッドI", 500)
THREAD run("スレッドJ", 550)
THREAD run("スレッドK", 600)
THREAD run("スレッドL", 650)

の部分を

// 通常呼び出し
run("スレッドA", 100)
run("スレッドA", 100)
run("スレッドB", 150)
run("スレッドC", 200)
run("スレッドD", 250)
run("スレッドE", 300)
run("スレッドF", 350)
run("スレッドG", 400)
run("スレッドH", 450)
run("スレッドI", 500)
run("スレッドJ", 550)
run("スレッドK", 600)
run("スレッドL", 650)

とすれば通常呼び出しになります。
通常で動作したときの動きが見れます。
この場合ひとつずつ呼び出されますね。

THREAD をつけて呼び出した FUNCTION や PROCEDURE が
独立したスレッドで動くっていう考え方でいいのかな?

試してないけど同期処理とかは行われなそうなので、
独自にやらないとだめな気がする。このテストでも

// ロックが解放されるまで待つ
WHILE LOCK
	SLEEP(0.01)
WEND
	// ロックして更新
LOCK = TRUE
FINISH_COUNT = FINISH_COUNT + 1
WINNER = WINNER + FINISH_COUNT + "位 " + msg + "<#CR>"
LOCK = FALSE

の辺りで試しにやってみた。

2006-05-30 追記

ロックの部分があれだと微妙だったので
もうちょっとちゃんと動きそうなものを考えてみた。

REPEAT
//	PRINT "現在" + LOCK + "がロックを取得中(by " + msg + ")"
	IF LOCK = "" THEN LOCK = msg
	SLEEP(0.01)
UNTIL LOCK = msg
FINISH_COUNT = FINISH_COUNT + 1
WINNER = WINNER + FINISH_COUNT + "位 " + msg + "<#CR>"
LOCK = ""

変数LOCKには引数のmsg(一意なメッセージ)を代入してそれをロック
とするように修正。こうすることによってこのスレッドでは
ロックが取得できるまで(LOCKに自分のメッセージが書き込めるまで)
ロックの取得を試み、取得できたあかつきには更新処理を行い
最後にLOCKに空文字""を代入することによってロックを開放している。