rafx_framework/resources/
resource_arc.rs1use crossbeam_channel::Sender;
2use std::fmt::Formatter;
3use std::hash::Hash;
4use std::sync::{Arc, Weak};
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
10pub(crate) struct ResourceId(pub(crate) u64);
11
12#[derive(Clone)]
16pub(crate) struct ResourceWithHash<ResourceT>
17where
18 ResourceT: Clone,
19{
20 pub(super) resource: ResourceT,
21 pub(super) resource_hash: ResourceId,
22}
23
24impl<ResourceT> std::fmt::Debug for ResourceWithHash<ResourceT>
25where
26 ResourceT: std::fmt::Debug + Clone,
27{
28 fn fmt(
29 &self,
30 f: &mut Formatter<'_>,
31 ) -> std::fmt::Result {
32 f.debug_struct("ResourceWithHash")
33 .field("resource", &self.resource)
34 .field("resource_hash", &self.resource_hash)
35 .finish()
36 }
37}
38
39struct ResourceArcInner<ResourceT>
40where
41 ResourceT: Clone,
42{
43 resource: ResourceWithHash<ResourceT>,
44 drop_tx: Sender<ResourceWithHash<ResourceT>>,
45}
46
47impl<ResourceT> Drop for ResourceArcInner<ResourceT>
48where
49 ResourceT: Clone,
50{
51 fn drop(&mut self) {
52 self.drop_tx.send(self.resource.clone())
53 .expect("A resource was dropped after the resource manager was destroyed, it might not clean up properly");
54 }
55}
56
57impl<ResourceT> std::fmt::Debug for ResourceArcInner<ResourceT>
58where
59 ResourceT: std::fmt::Debug + Clone,
60{
61 fn fmt(
62 &self,
63 f: &mut Formatter<'_>,
64 ) -> std::fmt::Result {
65 f.debug_struct("ResourceArcInner")
66 .field("resource", &self.resource)
67 .finish()
68 }
69}
70
71#[derive(Clone)]
72pub struct WeakResourceArc<ResourceT>
73where
74 ResourceT: Clone,
75{
76 inner: Weak<ResourceArcInner<ResourceT>>,
77 resource_hash: ResourceId,
78}
79
80impl<ResourceT> WeakResourceArc<ResourceT>
81where
82 ResourceT: Clone,
83{
84 pub fn upgrade(&self) -> Option<ResourceArc<ResourceT>> {
85 if let Some(upgrade) = self.inner.upgrade() {
86 Some(ResourceArc { inner: upgrade })
87 } else {
88 None
89 }
90 }
91}
92
93impl<ResourceT> std::fmt::Debug for WeakResourceArc<ResourceT>
94where
95 ResourceT: std::fmt::Debug + Clone,
96{
97 fn fmt(
98 &self,
99 f: &mut Formatter<'_>,
100 ) -> std::fmt::Result {
101 f.debug_struct("WeakResourceArc")
102 .field("inner", &self.inner)
103 .finish()
104 }
105}
106
107impl<ResourceT> PartialEq for WeakResourceArc<ResourceT>
108where
109 ResourceT: std::fmt::Debug + Clone,
110{
111 fn eq(
112 &self,
113 other: &Self,
114 ) -> bool {
115 self.resource_hash == other.resource_hash
116 }
117}
118
119impl<ResourceT> Eq for WeakResourceArc<ResourceT> where ResourceT: std::fmt::Debug + Clone {}
120
121impl<ResourceT> Hash for WeakResourceArc<ResourceT>
122where
123 ResourceT: std::fmt::Debug + Clone,
124{
125 fn hash<H: std::hash::Hasher>(
126 &self,
127 state: &mut H,
128 ) {
129 self.resource_hash.hash(state);
130 }
131}
132
133#[derive(Clone)]
134pub struct ResourceArc<ResourceT>
135where
136 ResourceT: Clone,
137{
138 inner: Arc<ResourceArcInner<ResourceT>>,
139}
140
141impl<ResourceT> ResourceArc<ResourceT>
142where
143 ResourceT: Clone,
144{
145 pub(crate) fn new(
146 resource: ResourceT,
147 resource_hash: ResourceId,
148 drop_tx: Sender<ResourceWithHash<ResourceT>>,
149 ) -> Self {
150 ResourceArc {
151 inner: Arc::new(ResourceArcInner {
152 resource: ResourceWithHash {
153 resource,
154 resource_hash,
155 },
156 drop_tx,
157 }),
158 }
159 }
160
161 pub fn get_raw(&self) -> ResourceT {
162 self.inner.resource.resource.clone()
163 }
164
165 pub(super) fn resource_hash(&self) -> ResourceId {
168 self.inner.resource.resource_hash
169 }
170
171 pub fn downgrade(&self) -> WeakResourceArc<ResourceT> {
172 let inner = Arc::downgrade(&self.inner);
173 let resource_hash = self.inner.resource.resource_hash;
174 WeakResourceArc {
175 inner,
176 resource_hash,
177 }
178 }
179}
180
181impl<ResourceT> std::fmt::Debug for ResourceArc<ResourceT>
182where
183 ResourceT: std::fmt::Debug + Clone,
184{
185 fn fmt(
186 &self,
187 f: &mut Formatter<'_>,
188 ) -> std::fmt::Result {
189 f.debug_struct("ResourceArc")
190 .field("inner", &self.inner)
191 .finish()
192 }
193}
194
195impl<ResourceT> PartialEq for ResourceArc<ResourceT>
196where
197 ResourceT: std::fmt::Debug + Clone,
198{
199 fn eq(
200 &self,
201 other: &Self,
202 ) -> bool {
203 self.inner.resource.resource_hash == other.inner.resource.resource_hash
204 }
205}
206
207impl<ResourceT> Eq for ResourceArc<ResourceT> where ResourceT: std::fmt::Debug + Clone {}
208
209impl<ResourceT> Hash for ResourceArc<ResourceT>
210where
211 ResourceT: std::fmt::Debug + Clone,
212{
213 fn hash<H: std::hash::Hasher>(
214 &self,
215 state: &mut H,
216 ) {
217 self.inner.resource.resource_hash.hash(state);
218 }
219}