module pind.samples.ja.concurrency.concurrency_5; import std.stdio; import std.random; import std.string; import std.concurrency; import core.thread; struct Position { int line; int column; string toString() { return format("%s,%s", line, column); } } struct Movement { Position from; Position to; string toString() { return ((from == to) ? format("%s (idle)", from) : format("%s -> %s", from, to)); } } class Robot { string image; Duration restDuration; this(string image, Duration restDuration) { this.image = image; this.restDuration = restDuration; } override string toString() { return format("%s(%s)", image, restDuration); } } /* 0,0付近のランダムな位置を返す。 */ Position randomPosition() { return Position(uniform!"[]"(-10, 10), uniform!"[]"(-10, 10)); } /* 指定された座標から最大1ステップ離れた位置を返す。 */ int randomStep(int current) { return current + uniform!"[]"(-1, 1); } /* 指定された位置の隣の位置を返す。 * 8方向のいずれかの隣の位置、 * または指定された位置自体になる場合もある。 */ Position randomNeighbor(Position position) { return Position(randomStep(position.line), randomStep(position.column)); } struct Job { size_t robotId; Position origin; Duration restDuration; } struct MovementMessage { size_t robotId; Movement movement; } void robotMover(Job job) { Position from = job.origin; while (true) { Thread.sleep(job.restDuration); Position to = randomNeighbor(from); Movement movement = Movement(from, to); from = to; ownerTid.send(MovementMessage(job.robotId, movement)); } } void main() { /* さまざまなrestDurationを持つロボット。 */ Robot[] robots = [ new Robot("A", 600.msecs), new Robot("B", 2000.msecs), new Robot("C", 5000.msecs) ]; /* 各ロボットの移動スレッドを開始する。 */ foreach (robotId, robot; robots) { spawn(&robotMover, Job(robotId, randomPosition(), robot.restDuration)); } /* ロボットの移動に関する情報を * 収集する準備ができた。 */ while (true) { auto message = receiveOnly!MovementMessage(); /* このロボットの移動を表示する。 */ writefln("%s %s", robots[message.robotId], message.movement); } }