/** * The <code>waitForNeighbors()</code> method is called from within the execution of a node when * that node needs to wait for its neighbors to catch up to it in execution time. The node will be * blocked until the other nodes in other threads catch up in global time. */ public void waitForNeighbors(long time) { // get the current simulator thread SimulatorThread thread = (SimulatorThread) Thread.currentThread(); SynchEvent event = (SynchEvent) threadMap.get(thread); // if the current thread is not in the synchronizer, do nothing if (event == null) return; WaitSlot w; synchronized (condition) { // allocate a wait slot for this thread w = insertWaiter(event, time); // check for other waiters and wake them if necessary WaitSlot h = checkWaiters(); // if we were at the head and just woken up, we can just return if (w == h) return; } // falling through means that we are either not at the head // or that not all threads have performed a meet or a wait try { // we must grab the lock for this wait slot synchronized (w) { // check for intervening wakeup between dropping global lock and taking local lock if (w.shouldWait) w.wait(); } } catch (InterruptedException e) { throw Util.unexpected(e); } }
private WaitSlot insertAfter(WaitSlot prev, WaitSlot w) { if (prev != null) { w.next = prev.next; prev.next = w; } else { waitSlotList = w; } return w; }
protected WaitSlot checkWaiters() { // have all threads reached either a meet or a wait? if (wait_count + meet_count < goal) return null; // are there any waiters at all? if (waitSlotList == null) return null; // there is a ready wait slot, wake those threads waiting on it WaitSlot h = waitSlotList; // move the wait list ahead to the next link waitSlotList = h.next; synchronized (h) { // notify the threads waiting on this wait slot h.shouldWait = false; h.notifyAll(); } // reduce the wait count by the number of waiters in this slot wait_count -= h.numWaiters; return h; }