@Internal public interface TaskMailbox
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.
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.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.
|
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 would have
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.
IllegalStateException
- if mailbox is already closed.void put(Mail mail)
Mails can be added from any thread.
mail
- the mail to enqueue.IllegalStateException
- if the mailbox is quiesced or closed.void putFirst(Mail mail)
Mails can be added from any thread.
mail
- the mail to enqueue.IllegalStateException
- if the mailbox is quiesced or closed.List<Mail> drain()
void quiesce()
IllegalStateException
.@Nonnull List<Mail> close()
IllegalStateException
. Returns all mails that were still enqueued.@Nonnull TaskMailbox.State getState()
TaskMailbox.State
.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–2020 The Apache Software Foundation. All rights reserved.