PredicateLock implements BspEvent { @Override public boolean waitMsecs(int msecs) { if (msecs < 0) { throw new RuntimeException("waitMsecs: msecs cannot be negative!"); } long maxMsecs = time.getMilliseconds() + msecs; int curMsecTimeout = 0; lock.lock(); try { while (!eventOccurred) { curMsecTimeout = Math.min(msecs, msecPeriod); if (LOG.isDebugEnabled()) { LOG.debug("waitMsecs: Wait for " + curMsecTimeout); } try { boolean signaled = cond.await(curMsecTimeout, TimeUnit.MILLISECONDS); if (LOG.isDebugEnabled()) { LOG.debug("waitMsecs: Got timed signaled of " + signaled); } } catch (InterruptedException e) { throw new IllegalStateException( "waitMsecs: Caught interrupted " + "exception on cond.await() " + curMsecTimeout, e); } if (time.getMilliseconds() > maxMsecs) { return false; } msecs = Math.max(0, msecs - curMsecTimeout); progressable.progress(); } } finally { lock.unlock(); } return true; } PredicateLock(Progressable progressable);  PredicateLock(Progressable progressable, int msecPeriod, Time time); @Override void reset(); @Override void signal(); @Override boolean waitMsecs(int msecs); @Override void waitForTimeoutOrFail(long timeout);  }
@Test public void testWaitMsecsNoEvent() { Time mockTime = mock(Time.class); when(mockTime.getMilliseconds()). thenReturn(0L).thenReturn(2L); BspEvent event = new PredicateLock(getStubProgressable(), 1, mockTime); boolean gotPredicate = event.waitMsecs(1); assertFalse(gotPredicate); assertEquals(0, progressCalled.get()); when(mockTime.getMilliseconds()). thenReturn(0L).thenReturn(0L).thenReturn(2L); gotPredicate = event.waitMsecs(1); assertFalse(gotPredicate); assertEquals(1, progressCalled.get()); }
@Test public void testWaitMsecs() { BspEvent event = new PredicateLock(getStubProgressable()); Thread signalThread = new SignalThread(event); signalThread.start(); boolean gotPredicate = event.waitMsecs(2000); assertTrue(gotPredicate); try { signalThread.join(); } catch (InterruptedException e) { } gotPredicate = event.waitMsecs(0); assertTrue(gotPredicate); }