org.curjent.impl.agent
Class Awaiters

java.lang.Object
  extended by org.curjent.impl.agent.Awaiters

final class Awaiters
extends Object

Common await implementations.

See Also:
Awaiter

Constructor Summary
Awaiters()
           
 
Method Summary
(package private) static boolean await(Awaiter awaiter, boolean synchronous, CallState state, long nanos)
          Common await implementation.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Awaiters

Awaiters()
Method Detail

await

static boolean await(Awaiter awaiter,
                     boolean synchronous,
                     CallState state,
                     long nanos)
              throws InterruptedException
Common await implementation. Waits until the condition is satisfied. Waits up to nanos nanoseconds before timing out. This call simply returns once the condition has been satisfied or the wait period has timed out; callers either recheck the condition or don't care.

synchronous is true for synchronous calls. More specifically, it is only true when this method is called by the Message.await() method. EXECUTING synchronous calls are special-cased; the Message.await() method simulates direct method calls. Support for this execution model is partially implemented here and in Deadlocks. Specifically, a DeadlockException is never thrown to the caller making the synchronous call while the message is running. In deadlock scenarios detected by curjent, at least one of the threads is waiting on a message that is not running, and it is the caller on one of those other threads that receives the deadlock exception.

Deadlock is defined only for infinite waits; i.e., where nanos == MAX_VALUE.

Agents can be configured to not check for deadlock by configuring the deadlock check interval to MAX_VALUE via AgentConfig.setDeadcheckTimeout(long, TimeUnit).

The await is either timed or not, where timed is true if nanos < MAX_VALUE. If timed, we wait at most nanos nanoseconds and never check for deadlock.

If not timed, we set check to AgentConfig.getDeadcheckTimeout(). This is the number of nanoseconds (if any) to wait before checking for deadlock the first time.

Object.wait may return before the requested duration has elapsed, so an inner loop is used to repeatedly wait until the intended duration has truly elapsed.

The first time the inner loop is entered, the wait duration is either the initial deadlock check delay for an infinite await, or equal to nanos for a timed await. For a timed await, the inner loop never exits until this method returns either because the condition is satisfied or nanos nanoseconds have elapsed.

The second and subsequent times into the inner loop, the inner loop waits forever until the message receives a notification via Object.notifyAll(). When notified, either the condition has potentially been satisfied and we return, or deadcheck has been set and we check for deadlock if eligible.

We are never eligible to check for deadlock the first time the inner loop is entered. In other words, requests for checking deadlock are ignored until at least check nanoseconds have elapsed first (which is initially set to the configured getDeadcheckTimeout value).

The second and subsequent times into the inner loop are always eligible to check for deadlock except for EXECUTING synchronous calls.

Throws:
InterruptedException


Copyright 2009-2011 Tom Landon
Apache License 2.0