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
FieldsModifier and TypeFieldDescriptionprivate intMessages added since startup; a monotonically increasing counter, callers read the difference over an interval.private intMost messages the pool holds.private intMessages dropped because the pool was full.private intMessages evicted for a higher priority one.private intIndex of the highest-priority live message; guarded by_lock.private final ObjectGuards every field below.private ArrayList<OutNetMessage> Sorted live region is[_head, size);[0, _head)is dequeued-but-not-yet-discarded.private final AtomicLongHands out the ordering sequence number.private static final intDead prefix length above which the backing array is compacted.Constructor Summary
ConstructorsConstructorDescriptionPrioritySendPool(int capacity) Sets the capacity, never below one, and sizes the backing list to match.Method Summary
Modifier and TypeMethodDescriptionprivate voidcompact()Move the live region to the front of a freshly sized backing list.voiddrainTo(ArrayList<OutNetMessage> target) Drain all messages into the target list (for resize).intSnapshot of added/evicted/dropped counters since construction.intThe configured pool capacity.intThe number of messages dropped since construction.intThe number of messages evicted since construction.private intinsertPosition(OutNetMessage msg, int from, int to) Binary search for the insertion point — highest priority first, FIFO within same priority (lower seqnum first).booleanoffer(OutNetMessage msg) Non-blocking offer with priority eviction.poll()Return the highest-priority message, or null if empty.intFree capacity remaining in the pool.voidsetCapacity(int newCapacity) Resize the pool.intsize()Number of messages currently in the pool.
Field Details
_lock
Guards every field below. Deliberately not_messages: compaction swaps the backing list, and a monitor has to outlive the object it guards._messages
Sorted live region is[_head, size);[0, _head)is dequeued-but-not-yet-discarded. Replaced wholesale by compaction._head
private int _headIndex of the highest-priority live message; guarded by_lock.COMPACT_MIN_HEAD
private static final int COMPACT_MIN_HEADDead prefix length above which the backing array is compacted.- See Also:
_seqNum
Hands out the ordering sequence number._capacity
private volatile int _capacityMost messages the pool holds._addedCount
private volatile int _addedCountMessages added since startup; a monotonically increasing counter, callers read the difference over an interval._evictedCount
private volatile int _evictedCountMessages evicted for a higher priority one._droppedCount
private volatile int _droppedCountMessages 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
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:
trueif added,falseif dropped
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_lockheld and the live region non-empty.drainTo
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 nextoffer(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
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 rangefrom- the first index to searchto- the index one past the last entry to search- Returns:
- the index within
[from, to)at which msg must be inserted