- it = thread_wq_map.find(thread_id);
- if (it == thread_wq_map.end()) {
- thread = new os::WorkQueue();
- thread_wq_map[thread_id] = thread;
- } else {
- thread = it->second;
+ RelayRace();
+
+ RelayRunner *
+ getRunner(unsigned leg);
+
+ void
+ startRace(void);
+
+ void
+ passBaton(trace::Call *call);
+
+ void
+ finishRace();
+};
+
+
+class RelayRunner
+{
+public:
+ RelayRace *race;
+ unsigned leg;
+ os::mutex mutex;
+ os::condition_variable wake_cond;
+
+ bool finished;
+ trace::Call *baton;
+ os::thread *thread;
+
+ static void *
+ runnerThread(RelayRunner *_this);
+
+ RelayRunner(RelayRace *race, unsigned _leg) :
+ race(race),
+ leg(_leg),
+ finished(false),
+ baton(0),
+ thread(0)
+ {
+ if (leg) {
+ thread = new os::thread(runnerThread, this);
+ }
+ }
+
+ void
+ runRace(void) {
+ os::unique_lock<os::mutex> lock(mutex);
+
+ while (1) {
+ while (!finished && !baton) {
+ wake_cond.wait(lock);
+ }
+
+ if (finished) {
+ break;
+ }
+
+ assert(baton);
+ trace::Call *call = baton;
+ baton = 0;
+
+ runLeg(call);
+ }
+
+ if (0) std::cerr << "leg " << leg << " actually finishing\n";
+
+ if (leg == 0) {
+ std::vector<RelayRunner*>::iterator it;
+ for (it = race->runners.begin() + 1; it != race->runners.end(); ++it) {
+ RelayRunner* runner = *it;
+ runner->finishRace();
+ }
+ }
+ }
+
+ void runLeg(trace::Call *call) {
+ do {
+ assert(call);
+ assert(call->thread_id == leg);
+ retraceCall(call);
+ delete call;
+ call = parser.parse_call();
+ } while (call && call->thread_id == leg);
+
+ if (call) {
+ assert(call->thread_id != leg);
+ flushRendering();
+ race->passBaton(call);
+ } else {
+ if (0) std::cerr << "finished on leg " << leg << "\n";
+ if (leg) {
+ race->finishRace();
+ } else {
+ finished = true;
+ }
+ }
+ }
+
+ void receiveBaton(trace::Call *call) {
+ assert (call->thread_id == leg);
+
+ mutex.lock();
+ baton = call;
+ mutex.unlock();
+
+ wake_cond.signal();
+ }
+
+ void finishRace() {
+ if (0) std::cerr << "notify finish to leg " << leg << "\n";
+
+ mutex.lock();
+ finished = true;
+ mutex.unlock();
+
+ wake_cond.signal();