pub struct FutureQueue<ST: SyncTypes, T: Send, F: QueuedFuture<T>> { /* private fields */ }Expand description
Process futures one after another, providing each exclusive access to some “arbitrated ressource”.
From a functionality perspective, a FutureQueue is very similar to an
asynchronous lock, where the lock is typically to be locked via polling and
the owner can then subsequently keep it for an indefinite amount of time,
e.g. across multiple poll() invocations on
some other Futures, until eventually releasing the lock again and waking
other waiters. However, this asynchronous lock scheme has the drawback that
it is not robust against threads “loosing interest”, e.g. tasks abandoned
for some reason: if the execution environment happens to not poll some lock
owning task any further, all other waiting tasks would end up stuck for
forever.
A FutureQueue solves this problem by assuming ownership of any future
needing access to the protected ressource and providing that (exclusively)
to its poll() once it becomes first in line. The
important point is that any poll() on
an enqueued future’s associated subscriptions
will always drive progress for any other enqueued futures ahead in line,
even if their original submitters ceased the polling. That way, any thread
polling on its enqueued future’s associated
subscription is guaranteed that its future will
eventually get processed.
As the enqueued future’s poll() had to get extended
in order to provide access to the FutureQueue arbitrated ressource, a new
trait QueuedFuture, otherwise resembling that of a standard Rust
Future is being defined. Users may enqueue implementations thereof via
FutureQueue::enqueue() and subsequently
poll on the resulting
EnqueuedFutureSubscription to drive their respective enqueued future’s
progress forward and eventually retrieve its result once
Ready.
Implementations§
Source§impl<ST: SyncTypes, T: Send, F: QueuedFuture<T>> FutureQueue<ST, T, F>
impl<ST: SyncTypes, T: Send, F: QueuedFuture<T>> FutureQueue<ST, T, F>
Sourcepub fn new(arbitrated_ressource: T) -> Self
pub fn new(arbitrated_ressource: T) -> Self
Crate a new FutureQueue instance.
Note that the caller is supposed to move the returned BroadcastFuture
into a pinned SyncRcPtr – the other parts of
the API expect that.
§Arguments:
arbitrated_ressource- The value to serialize access to. Provided as amutreference to enqueued future’spoll().
Sourcepub fn get_arbitrated_ressource_mut(&mut self) -> &mut T
pub fn get_arbitrated_ressource_mut(&mut self) -> &mut T
Access the wrapped arbitrated ressource through a mut reference on
Self.
Sourcepub fn enqueue<QP: SyncRcPtr<FutureQueue<ST, T, F>>>(
this: Pin<QP>,
fut: F,
) -> Result<EnqueuedFutureSubscription<ST, T, F, QP>, (F, FutureQueueError)>
pub fn enqueue<QP: SyncRcPtr<FutureQueue<ST, T, F>>>( this: Pin<QP>, fut: F, ) -> Result<EnqueuedFutureSubscription<ST, T, F, QP>, (F, FutureQueueError)>
Enqueue a future.
On success, a EnqueuedFutureSubscription will get returned, which
may get poll()ed to
drive the future’s progress forward and to eventually obtain its result.
On error, the future instance will get returned back to the caller alongside some error information. Note that returning the future back enables the caller to recover objects whose ownership had been passed temporarily into the future.
§Arguments:
this- APin<SyncRcPtr<Self>>theFutureQueuehad been wrapped in, c.f.Self::new().fut- The future to enqueue.