Skip to main content

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