Skip to content

Commit 51fe49b

Browse files
committed
allow iter() on Queue<_, QueueStateSync>
Create a guard type for a locked Queue instead of just reusing the guard of the underlying QueueState. The guard can have a single-argument iter() method, just like Queue<_, QueueState> has. Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 6f7a9dc commit 51fe49b

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

crates/virtio-queue/src/lib.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,35 @@ pub struct Queue<M: GuestAddressSpace, S: QueueStateT = QueueState> {
10131013
pub state: S,
10141014
}
10151015

1016+
/// A struct that holds an exclusive reference to a `QueueState` object, that was
1017+
/// obtained from a `Queue`. As such it remembers the associated GuestMemory object
1018+
/// and can use it to return an iterator.
1019+
pub struct QueueGuard<M: GuestAddressSpace, G: DerefMut<Target = QueueState>> {
1020+
mem: M::T,
1021+
guard: G,
1022+
}
1023+
1024+
impl<M: GuestAddressSpace, G: DerefMut<Target = QueueState>> Deref for QueueGuard<M, G> {
1025+
type Target = QueueState;
1026+
1027+
fn deref(&self) -> &Self::Target {
1028+
self.guard.deref()
1029+
}
1030+
}
1031+
1032+
impl<M: GuestAddressSpace, G: DerefMut<Target = QueueState>> DerefMut for QueueGuard<M, G> {
1033+
fn deref_mut(&mut self) -> &mut Self::Target {
1034+
self.guard.deref_mut()
1035+
}
1036+
}
1037+
1038+
impl<M: GuestAddressSpace, G: DerefMut<Target = QueueState>> QueueGuard<M, G> {
1039+
/// A consuming iterator over all available descriptor chain heads offered by the driver.
1040+
pub fn iter(&mut self) -> Result<AvailIter<'_, M::T>, Error> {
1041+
self.guard.iter(self.mem.clone())
1042+
}
1043+
}
1044+
10161045
impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
10171046
/// Construct an empty virtio queue with the given `max_size`.
10181047
pub fn new(mem: M, max_size: u16) -> Self {
@@ -1036,8 +1065,11 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
10361065
///
10371066
/// Logically this method will acquire the underlying lock protecting the `QueueState` Object.
10381067
/// The lock will be released when the returned object gets dropped.
1039-
pub fn lock(&mut self) -> <S::Guard as QueueStateGuard>::Out {
1040-
self.state.lock()
1068+
pub fn lock(&mut self) -> QueueGuard<M, <S::Guard as QueueStateGuard>::Out> {
1069+
QueueGuard {
1070+
mem: self.mem.memory(),
1071+
guard: self.state.lock(),
1072+
}
10411073
}
10421074

10431075
/// Get the maximum size of the virtio queue.

0 commit comments

Comments
 (0)