+ void finishRace() {
+ if (0) std::cerr << "notify finish to leg " << leg << "\n";
+
+ mutex.lock();
+ finished = true;
+ mutex.unlock();
+
+ wake_cond.signal();
+ }
+};
+
+void *
+RelayRunner::runnerThread(RelayRunner *_this) {
+ _this->runRace();
+ return 0;
+}
+
+
+RelayRace::RelayRace() {
+ runners.push_back(new RelayRunner(this, 0));
+}
+
+RelayRunner *
+RelayRace::getRunner(unsigned leg) {
+ RelayRunner *runner;
+
+ if (leg >= runners.size()) {
+ runners.resize(leg + 1);
+ runner = 0;
+ } else {
+ runner = runners[leg];
+ }
+ if (!runner) {
+ runner = new RelayRunner(this, leg);
+ runners[leg] = runner;
+ }
+ return runner;
+}
+
+void
+RelayRace::startRace(void) {
+ trace::Call *call;
+ call = parser.parse_call();
+
+ if (!call) {
+ return;
+ }
+
+ assert(call->thread_id == 0);
+
+ RelayRunner *foreRunner = getRunner(0);
+ if (call->thread_id == 0) {
+ foreRunner->baton = call;
+ } else {
+ passBaton(call);
+ }
+
+ foreRunner->runRace();
+}
+
+void
+RelayRace::passBaton(trace::Call *call) {
+ if (0) std::cerr << "switching to thread " << call->thread_id << "\n";
+ RelayRunner *runner = getRunner(call->thread_id);
+ runner->receiveBaton(call);
+}
+
+void
+RelayRace::finishRace(void) {
+ RelayRunner *runner = getRunner(0);
+ runner->finishRace();
+}
+
+
+static void
+mainLoop() {
+ addCallbacks(retracer);
+
+ long long startTime = 0;
+ frameNo = 0;
+
+ startTime = os::getTime();
+
+ RelayRace race;
+ race.startRace();