|
63 | 63 | //! - You don't need to do anything special in `Drop`. |
64 | 64 |
|
65 | 65 | use parking_lot::{Mutex, RwLock}; |
66 | | -use std::fmt::Debug; |
| 66 | +use std::fmt::{self, Debug, Display}; |
67 | 67 | use std::marker::PhantomData; |
68 | 68 | use std::mem; |
69 | 69 | use std::sync::Arc; |
@@ -145,6 +145,20 @@ pub trait MapMut: UserData { |
145 | 145 | F: FnOnce(&mut Self::Target) -> U; |
146 | 146 | } |
147 | 147 |
|
| 148 | +/// Trait for wrappers that can be mapped once. |
| 149 | +pub trait MapOwned: UserData { |
| 150 | + type Err: Debug; |
| 151 | + |
| 152 | + /// Maps a `T` to `U`. Called for methods that take `self`. This method may fail with |
| 153 | + /// an error if it is called more than once on the same object. |
| 154 | + /// |
| 155 | + /// Implementations of this method must not panic. Failures should be indicated by |
| 156 | + /// returning `Err`. |
| 157 | + fn map_owned<F, U>(&self, op: F) -> Result<U, Self::Err> |
| 158 | + where |
| 159 | + F: FnOnce(Self::Target) -> U; |
| 160 | +} |
| 161 | + |
148 | 162 | /// The default user data wrapper used by derive macro, when no `user_data` attribute is present. |
149 | 163 | /// This may change in the future. |
150 | 164 | pub type DefaultUserData<T> = LocalCellData<T>; |
@@ -440,6 +454,21 @@ impl<T, OPT> Clone for RwLockData<T, OPT> { |
440 | 454 | #[derive(Debug)] |
441 | 455 | pub struct ArcData<T>(Arc<T>); |
442 | 456 |
|
| 457 | +impl<T> ArcData<T> { |
| 458 | + /// Returns the internal `Arc<T>`. Useful for API's that require an `Arc` |
| 459 | + /// directly, or for coercing it into a trait object. |
| 460 | + /// |
| 461 | + /// Note that this removes |
| 462 | + /// the restriction of only being able to access the `NativeClass` instance |
| 463 | + /// temporarily through the `Map` trait; however, it should be exactly as safe |
| 464 | + /// as permanently storing an owned `ArcData` and then calling `.map()` on |
| 465 | + /// it later. |
| 466 | + #[inline] |
| 467 | + pub fn into_inner(self) -> Arc<T> { |
| 468 | + self.0 |
| 469 | + } |
| 470 | +} |
| 471 | + |
443 | 472 | unsafe impl<T> UserData for ArcData<T> |
444 | 473 | where |
445 | 474 | T: NativeClass + Send + Sync, |
@@ -732,3 +761,76 @@ where |
732 | 761 | Ok(op(&Default::default())) |
733 | 762 | } |
734 | 763 | } |
| 764 | + |
| 765 | +/// Special user-data wrapper intended for objects that can only be used once. Only |
| 766 | +/// implements `MapOwned`. |
| 767 | +pub struct Once<T>(Arc<atomic_take::AtomicTake<T>>); |
| 768 | + |
| 769 | +impl<T> Clone for Once<T> { |
| 770 | + #[inline] |
| 771 | + fn clone(&self) -> Self { |
| 772 | + Once(Arc::clone(&self.0)) |
| 773 | + } |
| 774 | +} |
| 775 | + |
| 776 | +unsafe impl<T> UserData for Once<T> |
| 777 | +where |
| 778 | + T: NativeClass + Send, |
| 779 | +{ |
| 780 | + type Target = T; |
| 781 | + |
| 782 | + #[inline] |
| 783 | + fn new(val: Self::Target) -> Self { |
| 784 | + Once(Arc::new(atomic_take::AtomicTake::new(val))) |
| 785 | + } |
| 786 | + |
| 787 | + #[inline] |
| 788 | + fn into_user_data(self) -> *const libc::c_void { |
| 789 | + Arc::into_raw(self.0) as *const _ |
| 790 | + } |
| 791 | + |
| 792 | + #[inline] |
| 793 | + unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self { |
| 794 | + Once(Arc::from_raw(ptr as *const _)) |
| 795 | + } |
| 796 | + |
| 797 | + #[inline] |
| 798 | + unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self { |
| 799 | + let borrowed = Arc::from_raw(ptr as *const _); |
| 800 | + let arc = Arc::clone(&borrowed); |
| 801 | + mem::forget(borrowed); |
| 802 | + Once(arc) |
| 803 | + } |
| 804 | +} |
| 805 | + |
| 806 | +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] |
| 807 | +pub struct ValueTaken; |
| 808 | + |
| 809 | +impl std::error::Error for ValueTaken {} |
| 810 | +impl Display for ValueTaken { |
| 811 | + #[inline] |
| 812 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 813 | + write!(f, "this object has already been used once") |
| 814 | + } |
| 815 | +} |
| 816 | + |
| 817 | +impl<T> MapOwned for Once<T> |
| 818 | +where |
| 819 | + T: NativeClass + Send, |
| 820 | +{ |
| 821 | + type Err = ValueTaken; |
| 822 | + |
| 823 | + /// Maps a `T` to `U`. Called for methods that take `self`. This method may fail with |
| 824 | + /// an error if it is called more than once on the same object. |
| 825 | + /// |
| 826 | + /// Implementations of this method must not panic. Failures should be indicated by |
| 827 | + /// returning `Err`. |
| 828 | + #[inline] |
| 829 | + fn map_owned<F, U>(&self, op: F) -> Result<U, Self::Err> |
| 830 | + where |
| 831 | + F: FnOnce(Self::Target) -> U, |
| 832 | + { |
| 833 | + let v = self.0.take().ok_or(ValueTaken)?; |
| 834 | + Ok(op(v)) |
| 835 | + } |
| 836 | +} |
0 commit comments