rafx_base/
resource_ref_map.rs

1use crate::memory::force_to_static_lifetime_mut;
2use crate::resource_map::{ReadBorrow, Resource, ResourceMap, WriteBorrow};
3use std::marker::PhantomData;
4use std::ops::{Deref, DerefMut};
5
6/// Like ResourceMap, but the insertions are temporary. This is an alternative to making a large
7/// amount of code generic just to pass down an arbitrary <T>
8#[derive(Default)]
9pub struct ResourceRefMap<'a> {
10    resources: ResourceMap,
11    phantom_data: PhantomData<&'a ()>,
12}
13
14impl<'a> ResourceRefMap<'a> {
15    pub fn new() -> Self {
16        ResourceRefMap::default()
17    }
18
19    /// Add a type/resource instance to the map
20    pub fn insert<R>(
21        &mut self,
22        r: &'a mut R,
23    ) where
24        R: Resource,
25    {
26        unsafe {
27            self.resources
28                .insert(ResourceRef(force_to_static_lifetime_mut(r)));
29        }
30    }
31
32    /// Remove a type/resource instance from the map
33    pub fn remove<R>(&mut self) -> Option<&'a mut R>
34    where
35        R: Resource,
36    {
37        self.resources.remove::<ResourceRef<R>>().map(|x| x.0)
38    }
39
40    /// Read-only fetch of a resource. Trying to get a resource that is not in the map is fatal. Use
41    /// try_fetch if unsure whether the resource exists. Requesting read access to a resource that
42    /// has any concurrently active writer is fatal.
43    pub fn fetch<R: Resource>(&self) -> ResourceRefBorrow<R> {
44        ResourceRefBorrow(self.resources.fetch::<ResourceRef<R>>())
45    }
46
47    /// Read-only fetch of a resource. Requesting read access to a resource that has a concurrently
48    /// active writer is fatal. Returns None if the type is not registered.
49    pub fn try_fetch<R: Resource>(&self) -> Option<ResourceRefBorrow<R>> {
50        self.resources.try_fetch().map(|x| ResourceRefBorrow(x))
51    }
52
53    /// Read/Write fetch of a resource. Trying to get a resource that is not in the map is fatal. Use
54    /// try_fetch if unsure whether the resource exists. Requesting write access to a resource with
55    /// any concurrently active read/write is fatal
56    pub fn fetch_mut<R: Resource>(&self) -> ResourceRefBorrowMut<R> {
57        ResourceRefBorrowMut(self.resources.fetch_mut::<ResourceRef<R>>())
58    }
59
60    /// Read/Write fetch of a resource. Requesting write access to a resource with
61    /// any concurrently active read/write is fatal. Returns None if the type is not registered.
62    pub fn try_fetch_mut<R: Resource>(&self) -> Option<ResourceRefBorrowMut<R>> {
63        self.resources
64            .try_fetch_mut()
65            .map(|x| ResourceRefBorrowMut(x))
66    }
67
68    /// Returns true if the resource is registered.
69    pub fn has_value<R>(&self) -> bool
70    where
71        R: Resource,
72    {
73        self.resources.has_value::<ResourceRef<R>>()
74    }
75}
76
77//
78// ResourceRef
79//
80
81// static reference is dangerous, must only be used when extracting
82pub struct ResourceRef<T: 'static>(&'static mut T);
83
84impl<T> ResourceRef<T> {
85    pub unsafe fn new(resources: &mut T) -> Self {
86        ResourceRef(force_to_static_lifetime_mut(resources))
87    }
88}
89
90impl<T> Deref for ResourceRef<T> {
91    type Target = T;
92
93    fn deref(&self) -> &Self::Target {
94        self.0
95    }
96}
97
98// unsafe impl<T> Send for ResourceRef<T> {}
99// unsafe impl<T> Sync for ResourceRef<T> {}
100
101//
102// ResourceRefBorrow
103//
104
105// static reference is dangerous, must only be used when extracting
106pub struct ResourceRefBorrow<'a, T: Resource>(ReadBorrow<'a, ResourceRef<T>>);
107
108impl<'a, T: Resource> ResourceRefBorrow<'a, T> {
109    pub fn new(resource: ReadBorrow<'a, ResourceRef<T>>) -> Self {
110        ResourceRefBorrow(resource)
111    }
112}
113
114impl<'a, T: Resource> Deref for ResourceRefBorrow<'a, T> {
115    type Target = T;
116
117    fn deref(&self) -> &Self::Target {
118        self.0 .0
119    }
120}
121
122//
123// ResourceRefBorrowMut
124//
125pub struct ResourceRefBorrowMut<'a, T: Resource>(WriteBorrow<'a, ResourceRef<T>>);
126
127impl<'a, T: Resource> ResourceRefBorrowMut<'a, T> {
128    pub fn new(resource: WriteBorrow<'a, ResourceRef<T>>) -> Self {
129        ResourceRefBorrowMut(resource)
130    }
131}
132
133impl<'a, T: Resource> Deref for ResourceRefBorrowMut<'a, T> {
134    type Target = T;
135
136    fn deref(&self) -> &Self::Target {
137        self.0 .0
138    }
139}
140
141impl<'a, T: Resource> DerefMut for ResourceRefBorrowMut<'a, T> {
142    fn deref_mut(&mut self) -> &mut Self::Target {
143        self.0 .0
144    }
145}
146
147//
148// tests
149//
150#[test]
151fn test_extract_resources() {
152    let mut resources = ResourceRefMap::default();
153    let mut x: i32 = 50;
154    resources.insert(&mut x);
155
156    {
157        let mut x_borrowed = resources.fetch_mut::<i32>();
158        assert_eq!(*x_borrowed, 50);
159        *x_borrowed += 10;
160    }
161
162    assert_eq!(x, 60);
163}