@Internal public interface TaskMailbox
The mailbox is bound to a mailbox thread passed during creation. Most operations may only
occur through that thread. Write operations (put(Mail)
, putFirst(Mail)
) can be
executed by any thread. All other methods can only be invoked by the mailbox thread, which is
passed upon construction. To verify that the current thread is allowed to take any mail, use
isMailboxThread()
, but all methods will perform the check themselves and fail
accordingly if called from another thread.
In the open state, the mailbox supports put and take operations. In the quiesced state, the mailbox supports only take operations.
A batch is a local view on the mailbox that does not contain simultaneously added mails similar to iterators of copy-on-write collections.
A batch serves two purposes: it reduces synchronization if more than one mail is processable at the time of the creation of a batch. Furthermore, it allows to divide the work of a mailbox in smaller logical chunks, such that the task threads cannot be blocked by a mail that enqueues itself and thus provides input starvation.
A batch is created with createBatch()
and consumed with tryTakeFromBatch()
.
Note that there is no blocking takeFromBatch
as batches can only be created and consumed
from the mailbox thread.
Also note that a batch can only be created in the MailboxProcessor.runMailboxLoop()
. A
batch must not be extended in any of the consuming methods as we may run into task input
starvation again. Assume a case where the mailbox loop handles a timeout event that produces a
record. That record is subsequently handled downstream, where it may lead to a MailboxExecutor.yield()
triggering another consumption method. If we extend the batch in any way
during that processing, we effectively lose the bounded processing guarantee of mails inside the
mailbox loop.
Modifier and Type | Interface and Description |
---|---|
static class |
TaskMailbox.MailboxClosedException
Exception thrown when
TaskMailbox is closed. |
static class |
TaskMailbox.State
This enum represents the states of the mailbox lifecycle.
|
Modifier and Type | Field and Description |
---|---|
static int |
MAX_PRIORITY
The maximal priority for mails.
|
static int |
MIN_PRIORITY
The minimal priority for mails.
|
Modifier and Type | Method and Description |
---|---|
List<Mail> |
close()
Close the mailbox.
|
boolean |
createBatch()
Creates a batch of mails that can be taken with
tryTakeFromBatch() . |
List<Mail> |
drain()
Drains the mailbox and returns all mails that were still enqueued.
|
TaskMailbox.State |
getState()
Returns the current state of the mailbox as defined by the lifecycle enum
TaskMailbox.State . |
boolean |
hasMail()
Returns
true if the mailbox contains mail. |
boolean |
isMailboxThread()
Check if the current thread is the mailbox thread.
|
void |
put(Mail mail)
Enqueues the given mail to the mailbox and blocks until there is capacity for a successful
put.
|
void |
putFirst(Mail mail)
Adds the given action to the head of the mailbox.
|
void |
quiesce()
Quiesce the mailbox.
|
void |
runExclusively(Runnable runnable)
Runs the given code exclusively on this mailbox.
|
int |
size()
Returns the current number of mails in this mailbox.
|
Mail |
take(int priority)
This method returns the oldest mail from the mailbox (head of queue) or blocks until a mail
is available.
|
Optional<Mail> |
tryTake(int priority)
Returns an optional with either the oldest mail from the mailbox (head of queue) if the
mailbox is not empty or an empty optional otherwise.
|
Optional<Mail> |
tryTakeFromBatch()
Returns an optional with either the oldest mail from the batch (head of queue) if the batch
is not empty or an empty optional otherwise.
|
static final int MIN_PRIORITY
static final int MAX_PRIORITY
boolean isMailboxThread()
Read operations will fail if they are called from another thread.
boolean hasMail()
true
if the mailbox contains mail.
Must be called from the mailbox thread (isMailboxThread()
.
Optional<Mail> tryTake(int priority)
Must be called from the mailbox thread (isMailboxThread()
.
IllegalStateException
- if mailbox is already closed.@Nonnull Mail take(int priority) throws InterruptedException
Must be called from the mailbox thread (isMailboxThread()
.
InterruptedException
- on interruption.IllegalStateException
- if mailbox is already closed.boolean createBatch()
tryTakeFromBatch()
. The batch does
not affect tryTake(int)
and take(int)
; that is, they return the same mails
even if no batch had been created.
The default batch is empty. Thus, this method must be invoked once before tryTakeFromBatch()
.
If a batch is not completely consumed by tryTakeFromBatch()
, its elements are
carried over to the new batch.
Must be called from the mailbox thread (isMailboxThread()
.
Optional<Mail> tryTakeFromBatch()
Must be called from the mailbox thread (isMailboxThread()
.
Note that there is no blocking takeFromBatch
as batches can only be created and
consumed from the mailbox thread.
TaskMailbox.MailboxClosedException
- if mailbox is already closed.void put(Mail mail)
Mails can be added from any thread.
mail
- the mail to enqueue.TaskMailbox.MailboxClosedException
- if the mailbox is quiesced or closed.void putFirst(Mail mail)
Mails can be added from any thread.
mail
- the mail to enqueue.TaskMailbox.MailboxClosedException
- if the mailbox is quiesced or closed.List<Mail> drain()
void quiesce()
TaskMailbox.MailboxClosedException
.@Nonnull List<Mail> close()
TaskMailbox.MailboxClosedException
. Returns all mails that were
still enqueued.@Nonnull TaskMailbox.State getState()
TaskMailbox.State
.int size()
void runExclusively(Runnable runnable)
put(Mail)
or modifying lifecycle methods).
Use this methods when you want to atomically execute code that uses different methods (e.g., check for state and then put message if open).
runnable
- the runnable to executeCopyright © 2014–2024 The Apache Software Foundation. All rights reserved.