Skip to content

Commit

Permalink
Add new method as_any() to GuestAddressSpace
Browse files Browse the repository at this point in the history
Add new method as_any() to GuestAddressSpace, which returns reference
to a std::any::Any trait object. Then downcast_ref() could be used to
get the concrete type of GuestAddressSpace trait object.

Signed-off-by: Liu Jiang <[email protected]>
  • Loading branch information
jiangliu committed Mar 8, 2022
1 parent c66e561 commit 828c0a2
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
27 changes: 25 additions & 2 deletions src/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
extern crate arc_swap;

use arc_swap::{ArcSwap, Guard};
use std::any::Any;
use std::ops::Deref;
use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError};

Expand Down Expand Up @@ -75,13 +76,17 @@ impl<M: GuestMemory> GuestMemoryAtomic<M> {
}
}

impl<M: GuestMemory> GuestAddressSpace for GuestMemoryAtomic<M> {
type T = GuestMemoryLoadGuard<M>;
impl<M: GuestMemory + 'static> GuestAddressSpace for GuestMemoryAtomic<M> {
type M = M;
type T = GuestMemoryLoadGuard<M>;

fn memory(&self) -> Self::T {
GuestMemoryLoadGuard { guard: self.load() }
}

fn as_any(&self) -> &dyn Any {
self
}
}

/// A guard that provides temporary access to a `GuestMemoryAtomic`. This
Expand Down Expand Up @@ -148,6 +153,24 @@ mod tests {
type GuestRegionMmap = crate::GuestRegionMmap<()>;
type GuestMemoryMmapAtomic = GuestMemoryAtomic<GuestMemoryMmap>;

#[test]
fn test_as_any() {
let region_size = 0x400;
let regions = vec![
(GuestAddress(0x0), region_size),
(GuestAddress(0x1000), region_size),
];
let mut iterated_regions = Vec::new();
let gmm = GuestMemoryMmap::from_ranges(&regions).unwrap();
let gm = GuestMemoryMmapAtomic::new(gmm);

assert!(gm
.as_any()
.downcast_ref::<GuestMemoryMmapAtomic>()
.is_some());
assert!(mem.as_any().downcast_ref::<String>().is_none());
}

#[test]
fn test_atomic_memory() {
let region_size = 0x400;
Expand Down
32 changes: 29 additions & 3 deletions src/guest_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
//! via pointers, references, or slices returned by methods of `GuestMemory`,`GuestMemoryRegion`,
//! `VolatileSlice`, `VolatileRef`, or `VolatileArrayRef`.

use std::any::Any;
use std::convert::From;
use std::fmt::{self, Display};
use std::fs::File;
Expand Down Expand Up @@ -400,33 +401,48 @@ pub trait GuestAddressSpace {
/// to access memory through this address space. The object provides
/// a consistent snapshot of the memory map.
fn memory(&self) -> Self::T;

/// Cast `self` to a dynamic trait object of `std::any::Any`.
fn as_any(&self) -> &dyn Any;
}

impl<M: GuestMemory> GuestAddressSpace for &M {
impl<M: GuestMemory + 'static> GuestAddressSpace for &M {
type M = M;
type T = Self;

fn memory(&self) -> Self {
self
}

fn as_any(&self) -> &dyn Any {
*self
}
}

impl<M: GuestMemory> GuestAddressSpace for Rc<M> {
impl<M: GuestMemory + 'static> GuestAddressSpace for Rc<M> {
type M = M;
type T = Self;

fn memory(&self) -> Self {
self.clone()
}

fn as_any(&self) -> &dyn Any {
self
}
}

impl<M: GuestMemory> GuestAddressSpace for Arc<M> {
impl<M: GuestMemory + 'static> GuestAddressSpace for Arc<M> {
type M = M;
type T = Self;

fn memory(&self) -> Self {
self.clone()
}

fn as_any(&self) -> &dyn Any {
self
}
}

/// Lifetime generic associated iterators. The actual iterator type is defined through associated
Expand Down Expand Up @@ -1256,4 +1272,14 @@ mod tests {
let r = mem.find_region(addr).unwrap();
assert_eq!(r.is_hugetlbfs(), None);
}

#[cfg(feature = "backend-mmap")]
#[test]
fn test_as_any() {
let addr = GuestAddress(0x1000);
let mem = &GuestMemoryMmap::from_ranges(&[(addr, 0x1000)]).unwrap();

assert!(mem.as_any().downcast_ref::<GuestMemoryMmap>().is_some());
assert!(mem.as_any().downcast_ref::<String>().is_none());
}
}

0 comments on commit 828c0a2

Please sign in to comment.