java.lang.Object
net.i2p.router.transport.PrioritySendPool

public final class PrioritySendPoolextends Object
Priority-aware bounded send pool for NTCP transport.

Client messages (PRIORITY_MY_DATA=1000) are always dequeued before transit messages (PRIORITY_PARTICIPATING=200). When the pool is full and a higher-priority message arrives, the lowest-priority message is evicted. Non-blocking: never stalls the caller.

Sorted array with binary search insertion — optimal for the small bounded sizes (64–8192) used by the NTCP send path. Synchronized on a private lock; contention is minimal because the thread that offers almost always polls immediately (handoff pattern).

The live region is [_head, _messages.size()): dequeue is a plain index bump, and the drained prefix is dropped wholesale once it is at least half the array, which keeps the insertion shift proportional to the live backlog rather than to capacity — at the tuned cap (cores * 512) a dequeue used to copy the whole array under the lock. Ordering is unchanged: the live region is still sorted by descending priority then ascending sequence number, so its first element is the highest-priority message and its last is the eviction victim.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private int
    Messages added since startup; a monotonically increasing counter, callers read the difference over an interval.
    private int
    Most messages the pool holds.
    private int
    Messages dropped because the pool was full.
    private int
    Messages evicted for a higher priority one.
    private int
    Index of the highest-priority live message; guarded by _lock.
    private final Object
    Guards every field below.
    Sorted live region is [_head, size); [0, _head) is dequeued-but-not-yet-discarded.
    private final AtomicLong
    Hands out the ordering sequence number.
    private static final int
    Dead prefix length above which the backing array is compacted.
  • Constructor Summary

    Constructors
    Constructor
    Description
    PrioritySendPool(int capacity)
    Sets the capacity, never below one, and sizes the backing list to match.
  • Method Summary

    Modifier and Type
    Method
    Description
    private void
    Move the live region to the front of a freshly sized backing list.
    void
    Drain all messages into the target list (for resize).
    int
    Snapshot of added/evicted/dropped counters since construction.
    int
    The configured pool capacity.
    int
    The number of messages dropped since construction.
    int
    The number of messages evicted since construction.
    private int
    insertPosition(OutNetMessage msg, int from, int to)
    Binary search for the insertion point — highest priority first, FIFO within same priority (lower seqnum first).
    boolean
    Non-blocking offer with priority eviction.
    Return the highest-priority message, or null if empty.
    int
    Free capacity remaining in the pool.
    void
    setCapacity(int newCapacity)
    Resize the pool.
    int
    Number of messages currently in the pool.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • _lock

      private final Object _lock
      Guards every field below. Deliberately not _messages: compaction swaps the backing list, and a monitor has to outlive the object it guards.
    • _messages

      private ArrayList<OutNetMessage> _messages
      Sorted live region is [_head, size); [0, _head) is dequeued-but-not-yet-discarded. Replaced wholesale by compaction.
    • _head

      private int _head
      Index of the highest-priority live message; guarded by _lock.
    • COMPACT_MIN_HEAD

      private static final int COMPACT_MIN_HEAD
      Dead prefix length above which the backing array is compacted.
      See Also:
    • _seqNum

      private final AtomicLong _seqNum
      Hands out the ordering sequence number.
    • _capacity

      private volatile int _capacity
      Most messages the pool holds.
    • _addedCount

      private volatile int _addedCount
      Messages added since startup; a monotonically increasing counter, callers read the difference over an interval.
    • _evictedCount

      private volatile int _evictedCount
      Messages evicted for a higher priority one.
    • _droppedCount

      private volatile int _droppedCount
      Messages dropped because the pool was full.
  • Constructor Details

    • PrioritySendPool

      public PrioritySendPool(int capacity)
      Sets the capacity, never below one, and sizes the backing list to match.
      Parameters:
      capacity - the maximum number of live messages, clamped up to a minimum of 1
  • Method Details

    • offer

      public boolean offer(OutNetMessage msg)
      Non-blocking offer with priority eviction.

      If the pool has room, the message is inserted in sorted position and the method returns true. If the pool is full and the incoming message has strictly higher priority than the lowest-priority message in the pool, the lowest is evicted and the new message takes its place. Otherwise the incoming message is dropped.

      Parameters:
      msg - the outbound message to enqueue
      Returns:
      true if added, false if dropped
    • poll

      public OutNetMessage poll()
      Return the highest-priority message, or null if empty. Highest priority first, FIFO within same priority.
      Returns:
      the head of the live region, or null if the pool holds nothing
    • compact

      private void compact()
      Move the live region to the front of a freshly sized backing list. Only called with _lock held and the live region non-empty.
    • drainTo

      public void drainTo(ArrayList<OutNetMessage> target)
      Drain all messages into the target list (for resize).
      Parameters:
      target - the list that receives the live messages; the pool is left empty afterwards
    • size

      public int size()
      Number of messages currently in the pool.
      Returns:
      the live count, excluding the dequeued-but-not-yet-compacted prefix
    • remainingCapacity

      public int remainingCapacity()
      Free capacity remaining in the pool.
      Returns:
      how many further messages fit before offers start evicting
    • getCapacity

      public int getCapacity()
      The configured pool capacity.
      Returns:
      how many messages the pool holds before further offers start evicting
    • setCapacity

      public void setCapacity(int newCapacity)
      Resize the pool. New capacity takes effect immediately; if the pool currently exceeds the new capacity, excess low-priority messages are evicted on the next offer(OutNetMessage).
      Parameters:
      newCapacity - the new maximum live depth, clamped up to a minimum of 1
    • getAddedCount

      public int getAddedCount()
      Snapshot of added/evicted/dropped counters since construction. Callers compute deltas over a time window.
      Returns:
      the added count
    • getEvictedCount

      public int getEvictedCount()
      The number of messages evicted since construction.
      Returns:
      the evicted count
    • getDroppedCount

      public int getDroppedCount()
      The number of messages dropped since construction.
      Returns:
      the dropped count
    • insertPosition

      private int insertPosition(OutNetMessage msg, int from, int to)
      Binary search for the insertion point — highest priority first, FIFO within same priority (lower seqnum first). The caller performs the insertion, so both call sites share the comparison but keep their own bookkeeping.
      Parameters:
      msg - the message being inserted, compared against the entries in range
      from - the first index to search
      to - the index one past the last entry to search
      Returns:
      the index within [from, to) at which msg must be inserted