最近、あろはさん萌えなんですが。コンパイラインストラクチャを作りたいなどと思ってる割に
なんもしてません。うぐは。CoinsのLIRとかの部分だけ、コンパイルしたら400ファイル以上classファイルできてて
やる気萎え。しかも、微妙とか言われとる。うーむ。


レジスタマシンなVMは高速なのかはよくわからんのでparrotのページ読んでみる。つづり怪しい。
うーむ。jakoとかいう謎言語があるらしい。jako?nekoと関係あるのか?
そういえば、neko vmはなんだったんだっけ?stackマシンかそうか。関係ないかな?
とにかくレジスタマシンだと並列処理用の最適化が有効だとかなんとか。
で、並列処理かぁ、そういえば今後のCPUとかどうなるのかとか考えてみるに、
マルチコアだよなぁ。と。じゃあ、マルチコア用、並列、coins?うーむ。
分かりません。Sunのスパークは64スレッドだとかなんとか。凄いな。fpgaとかいうのも出てきてるらしいし。
むー。GPUで並列とかなんかという話題もあったり。Jを見ると、非同期がどうのとあったり。


で、ふとマルチスレッドで非同期でゲーム作ってみたらいいんじゃって話を昔々にされたことを思い出したりなんかして。
マルチコアにそなえた、ゲームオブジェクトの書き方なんぞを考え始めてしまいました。
まぁ、こうなるんじゃねぇかなと。
まず、ゲームのオブジェクトのリストがあると。
で、そいつがキューにたまったような状態になってる。
で、各スレッドがそのキューから1個ずつゲームオブジェクトをとりだして、実行する。
で、終わったら、次のキューから1個取り出して処理する。キューが空になったら、1フレーム分の計算は終わり。
で、出来るだけ同期は取りたくないが、他のオブジェクトの状態をみたりしないといけないことがありえる。
この問題は参照透明性を維持するときっと嬉しいことがあるだろうから、計算前と計算後は2つに分離する。
他のオブジェクトは計算前のものを参照するのみにすることで解決したらいいだろう。
と、漠然と考えて、ソースを書き始めてみるうちに眠くなって寝る。


いちおそれっぽくなったソース。
なんというか、参照透明性みたいなことを考えたら、動くときには、新しいオブジェクト作って返す。
って形がいいのかなぁ、悪いのかなぁわからん。
世界の中には物が80個入っててスレッドが10個で全部を動かすと。
で、結果として新しい世界に新しいものが80個入る。
でも、Dataクラス以外は意識してないので破壊的代入しまくりだし。

import std.thread;
Object worldSync;
Object  stopSync;

class Data {
	int x;
	this() { move = &move1; }
	this(int x_, Data function(Data old) m) {
		x = x_;
		move = m;
	}
	Data function(Data old) move;
	static Data move1(Data old) {
		return new Data(old.x+1, &move2);
	}
	static Data move2(Data old) {
		return new Data(old.x, &move1);
	}
}

Data[][2] worlds;
Data[] world;
Data[] oldWorld;
int worldPos;

bool stop;
int  stopCount;
Thread[] threads;

int worldThread(void* p) {
	while (true) {
		while (worldPos < world.length) {
			int pos;
			synchronized (worldSync) {
				pos = worldPos++;
			}
			world[pos] = oldWorld[pos].move(oldWorld[pos]);
			printf("%d",world[pos].x);
		}
		int stopC;
		synchronized (stopSync) {
			stopC = ++stopCount;
		}
		if (stopC == threads.length) {// みんな待ってる。
			stopCount = 0;
			worldPos = 0;
			if  (world[0].x == 3) {
				printf("stop\n");
				stop = true;
				for (int i = 0; i < threads.length; i++) threads[i].resume();
				break;
			}
			// 世界を反転させる
			flipWorld();
			for (int i = 0; i < threads.length; i++) threads[i].resume();
			continue;
		}
		Thread.getThis().pause();
		if(stop)break;
	}
	return 0;
}

void initWorld() {
	threads.length = 10;
	worlds[0].length = worlds[1].length = 80;
	oldWorld = worlds[0];
	world    = worlds[1];
	worldSync = new Object();
	stopSync  = new Object();
	worldPos  = 0;
	stop = false;

	for (int j = 0; j < world.length;   j++) oldWorld[j] = new Data();
	for (int i = 0; i < threads.length; i++) threads[i] = new Thread(&worldThread, null);
	for (int i = 0; i < threads.length; i++) threads[i].start();
}
void flipWorld() {
	Data[] tmp = oldWorld;
	oldWorld   = world;
	world      = tmp;
}
void exitWorld() {
	for (int i = 0; i < threads.length; i++) threads[i].wait();
}

void main() {
	initWorld();
	exitWorld();
}