copyright The Portico Project 2008.

org.portico.lrc
Class LRCQueue

java.lang.Object
  extended by org.portico.lrc.LRCQueue

public class LRCQueue
extends Object

This class holds callback messages for the LRC. It also ensures the various required semantics relating to the status of the messages (TSO/RO) and the current status of the federate. For example, if a federate is constrained, the queue will appear empty of TSO messages until the current federate time has advanced such that those messages can be released.

Internally it implements two separate queues, one for receive order messages and another for timestamped messages. When polled, any receive order messages are released first, following this, any TSO messages are released as long as their time is less than or equal to the federate's current time.


Nested Class Summary
private  class LRCQueue.Sorter
          Comparator used for sorting TSO callback messages such that the callback queue remains ordered.
 
Field Summary
private  boolean async
           
private  Condition condition
           
private  boolean constrained
           
private  Lock lock
           
private  org.apache.log4j.Logger logger
           
private  LRC lrc
           
private  LRCState lrcState
           
private  BlockingQueue<FED_CallbackMessage> roQueue
           
private  PriorityBlockingQueue<FED_CallbackMessage> tsoQueue
           
 
Constructor Summary
LRCQueue(LRC lrc)
          Creates a new queue and associate it with the given LRC.
 
Method Summary
 boolean isEmpty()
           
 boolean offer(FED_CallbackMessage message)
          Place the message on the queue.
 FED_CallbackMessage peekTSO()
          This method will return the callback message at the head of the TSO queue, but it WILL NOT REMOVE IT.
 FED_CallbackMessage poll()
          Fetch the next available message from the queue.
 FED_CallbackMessage poll(long timeoutNanos)
          This method is the same as poll() except that if there are no messages available, it will block until there are (or until the timeout value has been reached).
private  FED_CallbackMessage pollForNonMessage()
          All this applies to RO messages only

The HLA specification says that if a federate: a) is constrained and b) does NOT have asynchronous delivery enabled and c) isn't in the middle of a time advance, then RO "messages" cannot be released to it.

private  void priorityMessage(FED_CallbackMessage message)
          Process a priority message.
protected  void setAsync(boolean async)
          Enable or Disable asynchronous delivery.
protected  void setConstrained(boolean constrained)
          Informs the queue of an update to the constrained status of the federate.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

lrc

private LRC lrc

lrcState

private LRCState lrcState

roQueue

private BlockingQueue<FED_CallbackMessage> roQueue

tsoQueue

private PriorityBlockingQueue<FED_CallbackMessage> tsoQueue

logger

private org.apache.log4j.Logger logger

constrained

private boolean constrained

async

private boolean async

lock

private Lock lock

condition

private Condition condition
Constructor Detail

LRCQueue

public LRCQueue(LRC lrc)
Creates a new queue and associate it with the given LRC.

Method Detail

offer

public boolean offer(FED_CallbackMessage message)
Place the message on the queue. Which internal queue it goes on to depends on the current status of the federation and the timestamp status of the message.

Timestamped messages will be ordered according to their time (lowest to highest). If the federate is *NOT* constrained, messages will automatically be stored in the RO queue (and will have their times set to PorticoConstants.NULL_TIME).

Returns:
true if the message was successfully added to the queue, false otherwise.

priorityMessage

private void priorityMessage(FED_CallbackMessage message)
Process a priority message. This will pass the message on to the callback sink right away (rather than queuing it). If there are exceptions or the request fails, this method will log them at the ERROR level.


poll

public FED_CallbackMessage poll()
Fetch the next available message from the queue.

The algorithm used to determine which message is next goes as follows:

  1. If there are any RO messages, they are removed first
  2. If there are no RO messages and the federates, the first message of the TSO queue is consulted
    1. If the timestamp of the first message is *less than or equal to* the current requested time for the federate, it is released
    2. If the timestamp of the first message is *greater than* the current requested time for the federate, no message is released and null is returned
As the TSO queue is ordered, the message with the lowest timestamp will always be at the head of the queue. Thus, it will be the first candidate to be released should the current requested time of the federate be of an appropriate value.


pollForNonMessage

private FED_CallbackMessage pollForNonMessage()
All this applies to RO messages only

The HLA specification says that if a federate: a) is constrained and b) does NOT have asynchronous delivery enabled and c) isn't in the middle of a time advance, then RO "messages" cannot be released to it. Sadly, the HLA spec also defines "messages" as (basically) reflections, interactions and removals. Everything else is not a "message" and thus can be happily delivered RO.

This method will find, remove and return from the RO queue the first non "message" callback message. Thus, in the situation above, it will return the first queued message that can happily be delivered, or null, if none exists

Returns:
The first RO message in the queue that can be delivered, or null, if none can

poll

public FED_CallbackMessage poll(long timeoutNanos)
                         throws InterruptedException
This method is the same as poll() except that if there are no messages available, it will block until there are (or until the timeout value has been reached). If the blocking thread is interrupted while waiting, an InterruptedException is thrown.

Throws:
InterruptedException

peekTSO

public FED_CallbackMessage peekTSO()
This method will return the callback message at the head of the TSO queue, but it WILL NOT REMOVE IT. This method should only be called by certain time-advancement handlers when processing event-based advance requests. If the TSO queue is empty, null is returned.


setConstrained

protected void setConstrained(boolean constrained)
Informs the queue of an update to the constrained status of the federate. If the value is false, all messages in the TSO queue will be moved over to the RO queue and will have their times set to PorticoConstants.NULL_TIME (thus making them RO)

This is part of a fix for issue PORT-103. Given that this method is synchronized, there will be no chance for a poll() to occur while there are still TSO messages in the queue if we have become unconstrained.


setAsync

protected void setAsync(boolean async)
Enable or Disable asynchronous delivery. This value should be sync'd up with the value in the LRCState. It is only mirrored here for efficiency sake. If asynchronous delivery is DISABLED, receive-order messages will only be released when the federate is in the time advancing state. NOTE, this is only a consideration if the federate is time constrained. If the federate is not time constrained (or it is, and async delivery is enabled), receive-order messages will be released whenever they are available.


isEmpty

public boolean isEmpty()
Returns:
Returns true if there are no messages queued for delivery (RO or TSO)

copyright The Portico Project 2008.