Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classShared dispatcher pool that multiplexes all internal I2CP message readers.Nested classes/interfaces inherited from class I2CPMessageReader
I2CPMessageReader.I2CPMessageEventListener, I2CPMessageReader.I2CPMessageReaderRunnerModifier and TypeClassDescriptionstatic interfaceDefines the different events the reader produces while reading the stream.protected classI2CPMessageReaderRunner.Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AtomicBooleanSet while a worker is serving this reader.private static final QueuedI2CPMessageReader.InternalI2CPDispatcherThe shared dispatcher feeding all the readers.private final I2CPMessageQueueThe queue messages are read from.(package private) static final intMessages one worker takes from a reader before requeueing it.private booleanTrue while the reader is registered with the dispatcher.Fields inherited from class I2CPMessageReader
__readerId, _listener, _reader, _readerThreadModifier and TypeFieldDescriptionprotected static final AtomicLongSource of the unique suffix each reader thread name carries.Listener notified of incoming messages, read errors and disconnects.Runnable doing the reading, owned by the reader thread.protected ThreadThread running the read loop.Constructor Summary
ConstructorsConstructorDescriptionCreates a new instance of this QueuedMessageReader and registers with the shared dispatcher.Method Summary
Modifier and TypeMethodDescriptionprivate booleanclaim()Take exclusive ownership of this reader for the calling worker.(package private) Stringdescribe()Name for diagnostics; identifies the session without depending on its internals.(package private) intdrainOnce(int maxMessages) Drain at most maxMessages, then return even if the queue is not empty.(package private) booleanWhether this reader is still reading and has messages waiting for a worker.(package private) booleanNon-blocking poll + dispatch.private booleanrelease()Give up ownership after a pass.voidRegister with the shared dispatcher.voidUnregister from the shared dispatcher.Methods inherited from class I2CPMessageReader
getListener, setListenerModifier and TypeMethodDescriptionCurrent message event listener.final voidListener for message events.
Field Details
in
The queue messages are read from.registered
private volatile boolean registeredTrue while the reader is registered with the dispatcher._claimed
Set while a worker is serving this reader.I2CP messages for one session are order-dependent, so exactly one worker may touch a reader at a time. Correctness would otherwise rest on the ready queue never holding two entries for the same reader. Claiming it before serving turns that into something the code enforces rather than something registration order has to uphold.
DISPATCHER
The shared dispatcher feeding all the readers.MAX_DRAIN_PER_PASS
static final int MAX_DRAIN_PER_PASSMessages one worker takes from a reader before requeueing it.- See Also:
Constructor Details
QueuedI2CPMessageReader
public QueuedI2CPMessageReader(I2CPMessageQueue in, I2CPMessageReader.I2CPMessageEventListener lsnr) Creates a new instance of this QueuedMessageReader and registers with the shared dispatcher. CallstartReading()to begin.- Parameters:
in- the in-JVM queue holding this session's incoming messageslsnr- notified with each message as it is dequeued for this session
Method Details
startReading
public void startReading()Register with the shared dispatcher. Idempotent: a second call must not put a duplicate entry in the ready queue, which would let two workers serve this reader concurrently and deliver its messages out of order.- Overrides:
startReadingin classI2CPMessageReader
stopReading
public void stopReading()Unregister from the shared dispatcher.- Overrides:
stopReadingin classI2CPMessageReader
processOnce
boolean processOnce()Non-blocking poll + dispatch. Called by a dispatcher worker.- Returns:
- true if a message was processed
drainOnce
int drainOnce(int maxMessages) Drain at most maxMessages, then return even if the queue is not empty.The bound is what stops one backed-up client from starving every other in-JVM client. Workers are pooled, so a reader that only returns once its queue is empty lets a payload flood hold a worker indefinitely while unrelated clients' queues back up until the router refuses to send to them at all. A full return value means more may be waiting, and the caller requeues the reader to continue.
- Parameters:
maxMessages- most messages to handle in this call- Returns:
- messages handled; equal to maxMessages when the queue was not drained
claim
private boolean claim()Take exclusive ownership of this reader for the calling worker.- Returns:
- false when another worker already owns it, or it stopped reading
release
private boolean release()Give up ownership after a pass.Reports only that the reader is still registered, which is not the same as having more to send: the dispatcher decides what to reoffer from the pass result and
needsService().- Returns:
- true when the reader is still reading
needsService
boolean needsService()Whether this reader is still reading and has messages waiting for a worker.This is the question the dispatcher's idle tick asks. It is deliberately not the same as
release(): release reports only that the reader is still registered, which says nothing about whether its queue holds anything.- Returns:
- true when a worker should serve this reader now
describe
String describe()Name for diagnostics; identifies the session without depending on its internals.- Returns:
- the listener class name (or "none") and this reader's identity hash