fyrox_core/pool/
handle.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::reflect::ReflectHandle;
22use crate::{
23    combine_uuids, pool::INVALID_GENERATION, reflect::prelude::*, uuid_provider,
24    visitor::prelude::*, TypeUuidProvider,
25};
26use serde::{Deserialize, Serialize};
27use std::any::{type_name, Any, TypeId};
28use std::{
29    cmp::Ordering,
30    fmt::{Debug, Display, Formatter},
31    hash::{Hash, Hasher},
32    marker::PhantomData,
33    sync::atomic::{self, AtomicUsize},
34};
35use uuid::Uuid;
36
37/// Handle is some sort of non-owning reference to content in a pool. It stores
38/// index of object and additional information that allows to ensure that handle
39/// is still valid (points to the same object as when handle was created).
40#[derive(Serialize, Deserialize)]
41pub struct Handle<T> {
42    /// Index of object in pool.
43    pub(super) index: u32,
44    /// Generation number, if it is same as generation of pool record at
45    /// index of handle then this is valid handle.
46    pub(super) generation: u32,
47    /// Type holder.
48    #[serde(skip)]
49    pub(super) type_marker: PhantomData<T>,
50}
51
52impl<T: Reflect> ReflectHandle for Handle<T> {
53    fn reflect_inner_type_id(&self) -> TypeId {
54        TypeId::of::<T>()
55    }
56
57    fn reflect_inner_type_name(&self) -> &'static str {
58        type_name::<T>()
59    }
60
61    fn reflect_is_some(&self) -> bool {
62        self.is_some()
63    }
64
65    fn reflect_set_index(&mut self, index: u32) {
66        self.index = index;
67    }
68
69    fn reflect_index(&self) -> u32 {
70        self.index
71    }
72
73    fn reflect_set_generation(&mut self, generation: u32) {
74        self.generation = generation;
75    }
76
77    fn reflect_generation(&self) -> u32 {
78        self.generation
79    }
80
81    fn reflect_as_erased(&self) -> ErasedHandle {
82        ErasedHandle::new(self.index, self.generation)
83    }
84}
85
86static INDEX_METADATA: FieldMetadata = FieldMetadata {
87    name: "Index",
88    display_name: "Index",
89    tag: "",
90    read_only: false,
91    immutable_collection: false,
92    min_value: None,
93    max_value: None,
94    step: None,
95    precision: None,
96    doc: "",
97};
98
99static GENERATION_METADATA: FieldMetadata = FieldMetadata {
100    name: "Generation",
101    display_name: "Generation",
102    tag: "",
103    read_only: false,
104    immutable_collection: false,
105    min_value: None,
106    max_value: None,
107    step: None,
108    precision: None,
109    doc: "",
110};
111
112impl<T: Reflect> Reflect for Handle<T> {
113    fn source_path() -> &'static str {
114        file!()
115    }
116
117    fn derived_types() -> &'static [TypeId]
118    where
119        Self: Sized,
120    {
121        T::derived_types()
122    }
123
124    fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
125        Some(Box::new(*self))
126    }
127
128    fn query_derived_types(&self) -> &'static [TypeId] {
129        Self::derived_types()
130    }
131
132    fn type_name(&self) -> &'static str {
133        type_name::<Self>()
134    }
135
136    fn doc(&self) -> &'static str {
137        ""
138    }
139
140    fn assembly_name(&self) -> &'static str {
141        env!("CARGO_PKG_NAME")
142    }
143
144    fn type_assembly_name() -> &'static str {
145        env!("CARGO_PKG_NAME")
146    }
147
148    fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) {
149        func(&[
150            {
151                FieldRef {
152                    metadata: &INDEX_METADATA,
153                    value: &self.index,
154                }
155            },
156            {
157                FieldRef {
158                    metadata: &GENERATION_METADATA,
159                    value: &self.generation,
160                }
161            },
162        ])
163    }
164
165    fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [FieldMut])) {
166        func(&mut [
167            {
168                FieldMut {
169                    metadata: &INDEX_METADATA,
170                    value: &mut self.index,
171                }
172            },
173            {
174                FieldMut {
175                    metadata: &GENERATION_METADATA,
176                    value: &mut self.generation,
177                }
178            },
179        ])
180    }
181
182    fn into_any(self: Box<Self>) -> Box<dyn Any> {
183        self
184    }
185
186    fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
187        func(self)
188    }
189
190    fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
191        func(self)
192    }
193
194    fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
195        func(self)
196    }
197
198    fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
199        func(self)
200    }
201
202    fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
203        let this = std::mem::replace(self, value.take()?);
204        Ok(Box::new(this))
205    }
206
207    fn as_handle(&self, func: &mut dyn FnMut(Option<&dyn ReflectHandle>)) {
208        func(Some(self))
209    }
210
211    fn as_handle_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectHandle>)) {
212        func(Some(self))
213    }
214}
215
216impl<T> Copy for Handle<T> {}
217
218impl<T> Eq for Handle<T> {}
219
220impl<T> PartialEq for Handle<T> {
221    #[inline]
222    fn eq(&self, other: &Handle<T>) -> bool {
223        self.generation == other.generation && self.index == other.index
224    }
225}
226
227impl<T> Hash for Handle<T> {
228    #[inline]
229    fn hash<H>(&self, state: &mut H)
230    where
231        H: Hasher,
232    {
233        self.index.hash(state);
234        self.generation.hash(state);
235    }
236}
237
238impl<T> Handle<T> {
239    pub const NONE: Handle<T> = Handle {
240        index: 0,
241        generation: INVALID_GENERATION,
242        type_marker: PhantomData,
243    };
244
245    #[inline(always)]
246    pub fn is_none(self) -> bool {
247        self.index == 0 && self.generation == INVALID_GENERATION
248    }
249
250    #[inline(always)]
251    pub fn is_some(self) -> bool {
252        !self.is_none()
253    }
254
255    #[inline(always)]
256    pub fn index(self) -> u32 {
257        self.index
258    }
259
260    #[inline(always)]
261    pub fn generation(self) -> u32 {
262        self.generation
263    }
264
265    #[inline(always)]
266    pub fn new(index: u32, generation: u32) -> Self {
267        Handle {
268            index,
269            generation,
270            type_marker: PhantomData,
271        }
272    }
273
274    #[inline(always)]
275    pub fn transmute<U>(&self) -> Handle<U> {
276        Handle {
277            index: self.index,
278            generation: self.generation,
279            type_marker: Default::default(),
280        }
281    }
282
283    #[inline(always)]
284    pub fn decode_from_u128(num: u128) -> Self {
285        Self {
286            index: num as u32,
287            generation: (num >> 32) as u32,
288            type_marker: Default::default(),
289        }
290    }
291
292    #[inline(always)]
293    pub fn encode_to_u128(&self) -> u128 {
294        (self.index as u128) | ((self.generation as u128) << 32)
295    }
296}
297
298impl<T> TypeUuidProvider for Handle<T>
299where
300    T: TypeUuidProvider,
301{
302    #[inline]
303    fn type_uuid() -> Uuid {
304        combine_uuids(
305            uuid::uuid!("30c0668d-7a2c-47e6-8c7b-208fdcc905a1"),
306            T::type_uuid(),
307        )
308    }
309}
310
311impl<T> PartialOrd for Handle<T> {
312    #[inline]
313    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
314        Some(self.cmp(other))
315    }
316}
317
318impl<T> Ord for Handle<T> {
319    #[inline]
320    fn cmp(&self, other: &Self) -> Ordering {
321        self.index.cmp(&other.index)
322    }
323}
324
325unsafe impl<T> Send for Handle<T> {}
326unsafe impl<T> Sync for Handle<T> {}
327
328impl<T> Display for Handle<T> {
329    #[inline]
330    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
331        write!(f, "{}:{}", self.index, self.generation)
332    }
333}
334
335/// Atomic handle.
336pub struct AtomicHandle(AtomicUsize);
337
338impl Clone for AtomicHandle {
339    #[inline]
340    fn clone(&self) -> Self {
341        Self(AtomicUsize::new(self.0.load(atomic::Ordering::Relaxed)))
342    }
343}
344
345impl Default for AtomicHandle {
346    #[inline]
347    fn default() -> Self {
348        Self::none()
349    }
350}
351
352impl AtomicHandle {
353    #[inline]
354    pub fn none() -> Self {
355        Self(AtomicUsize::new(0))
356    }
357
358    #[inline]
359    pub fn new(index: u32, generation: u32) -> Self {
360        let handle = Self(AtomicUsize::new(0));
361        handle.set(index, generation);
362        handle
363    }
364
365    #[inline]
366    pub fn set(&self, index: u32, generation: u32) {
367        let index = (index as usize) << (usize::BITS / 2) >> (usize::BITS / 2);
368        let generation = (generation as usize) << (usize::BITS / 2);
369        self.0.store(index | generation, atomic::Ordering::Relaxed);
370    }
371
372    #[inline]
373    pub fn set_from_handle<T>(&self, handle: Handle<T>) {
374        self.set(handle.index, handle.generation)
375    }
376
377    #[inline(always)]
378    pub fn is_some(&self) -> bool {
379        self.generation() != INVALID_GENERATION
380    }
381
382    #[inline(always)]
383    pub fn is_none(&self) -> bool {
384        !self.is_some()
385    }
386
387    #[inline]
388    pub fn index(&self) -> u32 {
389        let bytes = self.0.load(atomic::Ordering::Relaxed);
390        ((bytes << (usize::BITS / 2)) >> (usize::BITS / 2)) as u32
391    }
392
393    #[inline]
394    pub fn generation(&self) -> u32 {
395        let bytes = self.0.load(atomic::Ordering::Relaxed);
396        (bytes >> (usize::BITS / 2)) as u32
397    }
398}
399
400impl Display for AtomicHandle {
401    #[inline]
402    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
403        write!(f, "{}:{}", self.index(), self.generation())
404    }
405}
406
407impl Debug for AtomicHandle {
408    #[inline]
409    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
410        write!(f, "[Idx: {}; Gen: {}]", self.index(), self.generation())
411    }
412}
413
414/// Type-erased handle.
415#[derive(
416    Copy, Clone, Debug, Ord, PartialOrd, PartialEq, Eq, Hash, Reflect, Visit, Serialize, Deserialize,
417)]
418pub struct ErasedHandle {
419    /// Index of object in pool.
420    #[reflect(read_only)]
421    index: u32,
422    /// Generation number, if it is same as generation of pool record at
423    /// index of handle then this is valid handle.
424    #[reflect(read_only)]
425    generation: u32,
426}
427
428uuid_provider!(ErasedHandle = "50131acc-8b3b-40b5-b495-e2c552c94db3");
429
430impl Display for ErasedHandle {
431    #[inline]
432    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
433        write!(f, "{}:{}", self.index, self.generation)
434    }
435}
436
437impl Default for ErasedHandle {
438    #[inline]
439    fn default() -> Self {
440        Self::none()
441    }
442}
443
444impl<T> From<ErasedHandle> for Handle<T> {
445    #[inline]
446    fn from(erased_handle: ErasedHandle) -> Self {
447        Handle {
448            index: erased_handle.index,
449            generation: erased_handle.generation,
450            type_marker: PhantomData,
451        }
452    }
453}
454
455impl<T> From<AtomicHandle> for Handle<T> {
456    #[inline]
457    fn from(atomic_handle: AtomicHandle) -> Self {
458        Handle {
459            index: atomic_handle.index(),
460            generation: atomic_handle.generation(),
461            type_marker: PhantomData,
462        }
463    }
464}
465
466impl<T> From<Handle<T>> for ErasedHandle {
467    #[inline]
468    fn from(h: Handle<T>) -> Self {
469        Self {
470            index: h.index,
471            generation: h.generation,
472        }
473    }
474}
475
476impl ErasedHandle {
477    #[inline]
478    pub fn none() -> Self {
479        Self {
480            index: 0,
481            generation: INVALID_GENERATION,
482        }
483    }
484
485    #[inline]
486    pub fn new(index: u32, generation: u32) -> Self {
487        Self { index, generation }
488    }
489
490    #[inline(always)]
491    pub fn is_some(&self) -> bool {
492        self.generation != INVALID_GENERATION
493    }
494
495    #[inline(always)]
496    pub fn is_none(&self) -> bool {
497        !self.is_some()
498    }
499
500    #[inline(always)]
501    pub fn index(self) -> u32 {
502        self.index
503    }
504
505    #[inline(always)]
506    pub fn generation(self) -> u32 {
507        self.generation
508    }
509}
510
511impl<T> Visit for Handle<T> {
512    #[inline]
513    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
514        let mut region = visitor.enter_region(name)?;
515
516        self.index.visit("Index", &mut region)?;
517        self.generation.visit("Generation", &mut region)?;
518
519        Ok(())
520    }
521}
522
523impl<T> Default for Handle<T> {
524    #[inline]
525    fn default() -> Self {
526        Self::NONE
527    }
528}
529
530impl<T> Debug for Handle<T> {
531    #[inline]
532    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
533        write!(f, "[Idx: {}; Gen: {}]", self.index, self.generation)
534    }
535}
536
537#[cfg(test)]
538mod test {
539    use crate::{
540        pool::{AtomicHandle, ErasedHandle, Handle, INVALID_GENERATION},
541        visitor::{Visit, Visitor},
542    };
543
544    #[test]
545    fn test_handle_u128_encode_decode() {
546        let a = Handle::<()>::new(123, 321);
547        let encoded = a.encode_to_u128();
548        let decoded = Handle::<()>::decode_from_u128(encoded);
549        assert_eq!(decoded, a);
550    }
551
552    #[test]
553    fn erased_handle_none() {
554        assert_eq!(
555            ErasedHandle::none(),
556            ErasedHandle {
557                index: 0,
558                generation: INVALID_GENERATION,
559            }
560        );
561    }
562
563    #[test]
564    fn erased_handle_new() {
565        assert_eq!(
566            ErasedHandle::new(0, 1),
567            ErasedHandle {
568                index: 0,
569                generation: 1,
570            }
571        );
572    }
573
574    #[test]
575    fn erased_handle_is_some() {
576        assert!(ErasedHandle::new(0, 1).is_some());
577        assert!(!ErasedHandle::none().is_some());
578    }
579
580    #[test]
581    fn erased_handle_is_none() {
582        assert!(!ErasedHandle::new(0, 1).is_none());
583        assert!(ErasedHandle::none().is_none());
584    }
585
586    #[test]
587    fn erased_handle_index() {
588        assert_eq!(
589            ErasedHandle {
590                index: 42,
591                generation: 15
592            }
593            .index(),
594            42
595        );
596    }
597
598    #[test]
599    fn erased_handle_generation() {
600        assert_eq!(
601            ErasedHandle {
602                index: 42,
603                generation: 15
604            }
605            .generation(),
606            15
607        );
608    }
609
610    #[test]
611    fn default_for_erased_handle() {
612        assert_eq!(ErasedHandle::default(), ErasedHandle::none());
613    }
614
615    #[test]
616    fn erased_handle_from_handle() {
617        let handle = Handle::<u32> {
618            index: 0,
619            generation: 1,
620            type_marker: std::marker::PhantomData,
621        };
622
623        assert_eq!(
624            ErasedHandle::from(handle),
625            ErasedHandle {
626                index: 0,
627                generation: 1
628            }
629        );
630    }
631
632    #[test]
633    fn handle_from_erased_handle() {
634        let er = ErasedHandle {
635            index: 0,
636            generation: 1,
637        };
638
639        assert_eq!(
640            Handle::from(er),
641            Handle::<u32> {
642                index: 0,
643                generation: 1,
644                type_marker: std::marker::PhantomData,
645            }
646        );
647    }
648
649    #[test]
650    fn default_for_handle() {
651        assert_eq!(Handle::default(), Handle::<u32>::NONE);
652    }
653
654    #[test]
655    fn visit_for_handle() {
656        let mut h = Handle::<u32>::default();
657        let mut visitor = Visitor::default();
658
659        assert!(h.visit("name", &mut visitor).is_ok());
660    }
661
662    #[test]
663    fn test_debug_for_handle() {
664        let h = Handle::<u32> {
665            index: 0,
666            generation: 1,
667            type_marker: std::marker::PhantomData,
668        };
669
670        assert_eq!(format!("{h:?}"), "[Idx: 0; Gen: 1]");
671    }
672
673    #[test]
674    fn handle_getters() {
675        let h = Handle::<u32> {
676            index: 0,
677            generation: 1,
678            type_marker: std::marker::PhantomData,
679        };
680
681        assert_eq!(h.index(), 0);
682        assert_eq!(h.generation(), 1);
683    }
684
685    #[test]
686    fn handle_transmute() {
687        assert_eq!(
688            Handle::<u32>::default().transmute::<f32>(),
689            Handle::<f32>::default()
690        );
691    }
692
693    #[test]
694    fn test_atomic_handle() {
695        let handle = AtomicHandle::new(123, 321);
696        assert!(handle.is_some());
697        assert_eq!(handle.index(), 123);
698        assert_eq!(handle.generation(), 321);
699
700        let handle = AtomicHandle::default();
701        assert!(handle.is_none());
702    }
703}