thin_cell/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
4#![deny(rustdoc::broken_intra_doc_links)]
5
6mod state;
7
8mod fat_ptr;
9
10pub mod sync;
11pub mod unsync;
12
13macro_rules! thin_cell {
14 {
15 $( #[$doc:meta] )*
16 } => {
17 use std::{
18 any::{Any, TypeId},
19 cell::UnsafeCell,
20 fmt::{self, Debug, Display},
21 marker::PhantomData,
22 mem::ManuallyDrop,
23 ops::{Deref, DerefMut},
24 ptr::NonNull,
25 };
26
27 use crate::fat_ptr::*;
28
29 /// The inner allocation of `ThinCell`
30 ///
31 /// This should not be used except in unsize coercion solely as a type.
32 #[repr(C)]
33 pub struct Inner<T: ?Sized> {
34 // metadata MUST be at offset 0 so that `*mut Inner<T>` is also a valid `*mut usize`
35 // points to the metadata
36 metadata: usize,
37 state: State,
38 data: UnsafeCell<T>,
39 }
40
41 $( #[$doc] )*
42 pub struct ThinCell<T: ?Sized> {
43 ptr: NonNull<()>,
44 _marker: PhantomData<Inner<T>>,
45 }
46
47 /// A mutable guard returned by [`ThinCell::borrow`]
48 pub struct Ref<'a, T: ?Sized> {
49 value: &'a mut T,
50 state: &'a State,
51 }
52
53 /// A weak reference to a [`ThinCell`] that doesn't prevent dropping.
54 ///
55 /// `Weak` references don't keep the value alive. The value will be dropped
56 /// when all strong references (`ThinCell`) are dropped, even if weak
57 /// references still exist.
58 ///
59 /// Use [`Weak::upgrade`] to attempt to convert a weak reference back to a
60 /// strong reference (`ThinCell`). This will fail if the value has already
61 /// been dropped.
62 #[cfg(feature = "weak")]
63 pub struct Weak<T: ?Sized> {
64 ptr: NonNull<()>,
65 _marker: PhantomData<Inner<T>>,
66 }
67
68 impl<T> ThinCell<T> {
69 /// Creates a new `ThinCell` wrapping the given data.
70 pub fn new(data: T) -> Self {
71 let alloc = Box::new(Inner {
72 metadata: 0,
73 state: State::new(),
74 data: UnsafeCell::new(data),
75 });
76
77 let ptr = Box::into_raw(alloc);
78
79 ThinCell {
80 ptr: unsafe { NonNull::new_unchecked(ptr as _) },
81 _marker: PhantomData,
82 }
83 }
84
85 /// Consumes the `ThinCell` and try to get inner value.
86 ///
87 /// Returns the inner value in [`Ok`] if there are no other owners and it is
88 /// not currently borrowed, return `Err(self)` otherwise.
89 pub fn try_unwrap(self) -> Result<T, Self> {
90 if !self.inner().state.try_unwrap() {
91 return Err(self);
92 }
93
94 // SAFETY: As tested above, there are no other owners and it is not borrowed
95 Ok(unsafe { self.unwrap_unchecked() })
96 }
97
98 /// Consumes the `ThinCell`, returning the inner value.
99 ///
100 /// # Safety
101 /// The caller must guarantee that there are no other owners and it is not
102 /// currently borrowed.
103 #[cfg(not(feature = "weak"))]
104 pub unsafe fn unwrap_unchecked(self) -> T {
105 let this = ManuallyDrop::new(self);
106 // SAFETY: guaranteed by caller to have unique ownership and is not borrowed
107 let inner = unsafe { Box::from_raw(this.inner_ptr() as *mut Inner<T>) };
108
109 inner.data.into_inner()
110 }
111
112 /// Consumes the `ThinCell`, returning the inner value.
113 ///
114 /// # Safety
115 /// The caller must guarantee that there are no other strong owners and it is not
116 /// currently borrowed.
117 #[cfg(feature = "weak")]
118 pub unsafe fn unwrap_unchecked(self) -> T {
119 let this = ManuallyDrop::new(self);
120 let inner = this.inner();
121
122 let _weak: Weak<T> = Weak {
123 ptr: this.ptr,
124 _marker: PhantomData,
125 };
126
127 // SAFETY: guaranteed by caller to have unique strong ownership and
128 // not be borrowed. This moves out `T` without touching the
129 // allocation so outstanding weak refs remain valid.
130 unsafe { std::ptr::read(inner.data.get()) }
131 }
132 }
133
134 impl<T: ?Sized> ThinCell<T> {
135 const IS_SIZED: bool = is_sized::<T>();
136
137 /// Reconstructs the raw pointer to the inner allocation.
138 fn inner_ptr(&self) -> *const Inner<T> {
139 let ptr = self.ptr.as_ptr();
140
141 if Self::IS_SIZED {
142 // SIZED CASE: Cast pointer-to-pointer
143 // Doing this trick to workaround Rust not allowing `ptr as *const Inner<T>`
144 // due to `T` being `?Sized` directly even when we know it's `Sized`
145 let ptr_ref = &ptr as *const *mut () as *const *const Inner<T>;
146
147 // SAFETY: `self.ptr` is a valid pointer of `Inner<T>`
148 unsafe { *ptr_ref }
149 } else {
150 // UNSIZED CASE: Read metadata
151 // SAFETY: pointer returned by `self.ptr` is valid, and `metadata` is at offset
152 // 0 of `Inner<T>`, which is guaranteed by `repr(C)` and the definition of
153 // `Inner<T>`
154 let metadata = unsafe { *(ptr as *const usize) };
155
156 // Miri will complain about this:
157 // - https://github.com/thepowersgang/stack_dst-rs/issues/14
158 // - https://github.com/uazu/stakker/blob/5821c30409c19ca9167808b669c928c94bc5f177/src/queue/flat.rs#L14-L17
159 // But this should be sound as per Rust's fat pointer and metadata construction
160 FatPtr { ptr, metadata }.into_ptr()
161 }
162 }
163
164 /// Returns a reference to the inner allocation.
165 fn inner(&self) -> &Inner<T> {
166 unsafe { &*self.inner_ptr() }
167 }
168
169 /// Returns a reference to the state cell.
170 fn state(&self) -> &State {
171 &self.inner().state
172 }
173
174 /// Deallocates the inner allocation.
175 ///
176 /// # Safety
177 ///
178 /// `self` must be the last owner and it must not be used after this call.
179 #[cfg(not(feature = "weak"))]
180 unsafe fn drop_in_place(&mut self) {
181 drop(unsafe { Box::from_raw(self.inner_ptr() as *mut Inner<T>) })
182 }
183
184 /// Leaks the `ThinCell`, returning a raw pointer to the inner allocation.
185 ///
186 /// The returned pointer points to the inner allocation. To restore the
187 /// `ThinCell`, use [`ThinCell::from_raw`].
188 pub fn leak(self) -> *mut () {
189 let this = ManuallyDrop::new(self);
190 this.ptr.as_ptr()
191 }
192
193 /// Reconstructs a `ThinCell<T>` from a raw pointer.
194 ///
195 /// # Safety
196 /// The pointer must have been obtained from a previous call to
197 /// [`ThinCell::leak`], and the [`ThinCell`] must not have been dropped in
198 /// the meantime.
199 pub unsafe fn from_raw(ptr: *mut ()) -> Self {
200 ThinCell {
201 // SAFETY: caller guarantees `ptr` is valid
202 ptr: unsafe { NonNull::new_unchecked(ptr) },
203 _marker: PhantomData,
204 }
205 }
206
207 /// Returns the number of strong owners.
208 pub fn count(&self) -> usize {
209 self.state().load().count()
210 }
211
212 /// Borrows the value mutably.
213 ///
214 /// Returns a [`Ref`] guard that provides mutable access to the inner value.
215 /// The borrow lasts until the guard is dropped. See module-level documentation
216 /// for details on borrowing behavior.
217 ///
218 /// # Examples
219 ///
220 /// ```
221 /// # use thin_cell::unsync::ThinCell;
222 /// let cell = ThinCell::new(5);
223 ///
224 /// {
225 /// let mut borrowed = cell.borrow();
226 /// *borrowed = 10;
227 /// } // borrow is released here
228 ///
229 /// assert_eq!(*cell.borrow(), 10);
230 /// ```
231 pub fn borrow(&self) -> Ref<'_, T> {
232 let inner = self.inner();
233 inner.state.borrow();
234
235 // SAFETY: We have exclusive access via borrow flag and block further access
236 // with `Ordering::Acquire`/`Release` pair.
237 let value = unsafe { &mut *inner.data.get() };
238
239 Ref {
240 value,
241 state: &inner.state,
242 }
243 }
244
245 /// Attempts to borrow the value mutably.
246 ///
247 /// Returns `Some(Ref)` if the value is not currently borrowed, or `None` if
248 /// it is already borrowed.
249 ///
250 /// This is the non-blocking variant of [`borrow`](ThinCell::borrow).
251 ///
252 /// # Examples
253 ///
254 /// ```
255 /// # use thin_cell::unsync::ThinCell;
256 /// let cell = ThinCell::new(5);
257 ///
258 /// let borrow1 = cell.borrow();
259 /// assert!(cell.try_borrow().is_none()); // Already borrowed
260 /// drop(borrow1);
261 /// assert!(cell.try_borrow().is_some()); // Now available
262 /// ```
263 pub fn try_borrow(&self) -> Option<Ref<'_, T>> {
264 let inner = self.inner();
265 if !inner.state.try_borrow() {
266 return None;
267 }
268
269 // SAFETY: We have exclusive access via borrow flag and block further access
270 // with `Ordering::Acquire`/`Release` pair.
271 let value = unsafe { &mut *inner.data.get() };
272
273 Some(Ref {
274 value,
275 state: &inner.state,
276 })
277 }
278
279 /// Get a mutable reference to the inner value without any checks.
280 ///
281 /// # Safety
282 ///
283 /// The caller must guarantee that there are no other owners and it is not
284 /// borrowed now and during the entire lifetime of the returned reference.
285 pub unsafe fn borrow_unchecked(&mut self) -> &mut T {
286 let inner = self.inner();
287 unsafe { &mut *inner.data.get() }
288 }
289
290 /// Creates a new `ThinCell<U>` from `data: U` and coerces it to
291 /// `ThinCell<T>`.
292 ///
293 /// # Safety
294 ///
295 /// `coerce` function must ensure the returned pointer is:
296 ///
297 /// - a valid unsizing of `Inner<T>`, e.g., some `Inner<dyn Trait>` or
298 /// `Inner<[_]>`
299 /// - with same address (bare data pointer without metadata) as input
300 pub unsafe fn new_unsize<U>(
301 data: U,
302 coerce: impl Fn(*const Inner<U>) -> *const Inner<T>,
303 ) -> Self {
304 let this = ThinCell::new(data);
305 // SAFETY: We're holding unique ownership and is not borrowed.
306 unsafe { this.unsize_unchecked(coerce) }
307 }
308
309 /// Manually coerce to unsize.
310 ///
311 /// # Safety
312 ///
313 /// `coerce` has the same requirements as [`ThinCell::new_unsize`].
314 ///
315 /// # Panics
316 ///
317 /// Panics if the `ThinCell` is currently shared (count > 1) or borrowed.
318 ///
319 /// See [`ThinCell::unsize_unchecked`] for details.
320 pub unsafe fn unsize<U: ?Sized>(
321 self,
322 coerce: impl Fn(*const Inner<T>) -> *const Inner<U>,
323 ) -> ThinCell<U> {
324 let inner = self.inner();
325 let s = inner.state.load();
326
327 assert!(!s.is_shared(), "Cannot coerce shared `ThinCell`");
328 assert!(!s.is_borrowed(), "Cannot coerce borrowed `ThinCell`");
329
330 // SAFETY: As tested above, the `ThinCell` is:
331 // - not shared, and
332 // - not borrowed
333 // - validity of `coerce` is guaranteed by caller
334 unsafe { self.unsize_unchecked(coerce) }
335 }
336
337 /// Manually coerce to unsize without checks.
338 ///
339 /// # Safety
340 ///
341 /// - The `ThinCell` must have unique ownership (count == 1)
342 /// - The `ThinCell` must not be borrowed
343 /// - `coerce` has the same requirements as [`ThinCell::new_unsize`].
344 ///
345 /// In particular, first two requirement is the exact state after
346 /// [`ThinCell::new`].
347 pub unsafe fn unsize_unchecked<U: ?Sized>(
348 self,
349 coerce: impl Fn(*const Inner<T>) -> *const Inner<U>,
350 ) -> ThinCell<U> {
351 let this = ManuallyDrop::new(self);
352
353 let old_ptr = this.inner_ptr();
354 let fat_ptr = coerce(old_ptr);
355
356 let FatPtr { ptr, metadata } = FatPtr::from_ptr::<Inner<U>>(fat_ptr);
357
358 // SAFETY: `Inner` is `repr(C)` and has `metadata` at offset 0
359 unsafe { *(old_ptr as *mut usize) = metadata };
360
361 ThinCell {
362 // SAFETY: `ptr` is valid as it comes from `self`
363 ptr: unsafe { NonNull::new_unchecked(ptr) },
364 _marker: PhantomData,
365 }
366 }
367
368 /// Returns the raw pointer to the inner allocation.
369 pub fn as_ptr(&self) -> *const () {
370 self.ptr.as_ptr()
371 }
372
373 /// Returns `true` if the two `ThinCell`s point to the same allocation.
374 pub fn ptr_eq(&self, other: &Self) -> bool {
375 std::ptr::eq(self.as_ptr(), other.as_ptr())
376 }
377
378 /// Downcasts the `ThinCell<T>` to `ThinCell<U>`.
379 ///
380 /// # Safety
381 ///
382 /// The caller must make sure that the inner value is actually of type `U`.
383 pub unsafe fn downcast_unchecked<U>(self) -> ThinCell<U> {
384 let this = ManuallyDrop::new(self);
385
386 ThinCell {
387 ptr: this.ptr,
388 _marker: PhantomData,
389 }
390 }
391 }
392
393 #[cfg(feature = "weak")]
394 impl<T: ?Sized> ThinCell<T> {
395 /// Returns the number of strong references.
396 pub fn strong_count(&self) -> usize {
397 self.state().load().strong_count()
398 }
399
400 /// Returns the number of weak references.
401 pub fn weak_count(&self) -> usize {
402 self.state().load().weak_count()
403 }
404
405 /// Creates a new weak reference to this `ThinCell`.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// # #[cfg(feature = "weak")]
411 /// # {
412 /// # use thin_cell::sync::ThinCell;
413 /// let cell = ThinCell::new(42);
414 /// let weak = cell.downgrade();
415 ///
416 /// assert_eq!(cell.strong_count(), 1);
417 /// assert_eq!(cell.weak_count(), 2);
418 ///
419 /// drop(cell);
420 /// assert!(weak.upgrade().is_none());
421 /// # }
422 /// ```
423 pub fn downgrade(&self) -> Weak<T> {
424 self.state().inc_weak();
425 Weak {
426 ptr: self.ptr,
427 _marker: PhantomData,
428 }
429 }
430 }
431
432 impl<T, const N: usize> ThinCell<[T; N]> {
433 /// Coerce an array [`ThinCell`] to a slice one.
434 pub fn unsize_slice(self) -> ThinCell<[T]> {
435 // Safety: unsized coercion from array to slice is safe
436 unsafe { self.unsize(|ptr| ptr as _) }
437 }
438 }
439
440 /// Error returned by [`ThinCell::downcast`] when downcasting fails.
441 #[derive(Debug)]
442 pub enum DowncastError<T: ?Sized> {
443 /// The [`ThinCell`] is currently borrowed.
444 Borrowed(ThinCell<T>),
445
446 /// The inner value is not of the target type.
447 Type(ThinCell<T>),
448 }
449
450 impl<T: ?Sized> DowncastError<T> {
451 /// Consumes the error and returns the original `ThinCell<T>`.
452 pub fn into_inner(self) -> ThinCell<T> {
453 match self {
454 DowncastError::Borrowed(cell) | DowncastError::Type(cell) => cell,
455 }
456 }
457 }
458
459 impl<T: Any + ?Sized> ThinCell<T> {
460 /// Attempts to downcast the `ThinCell<T>` to `ThinCell<U>`.
461 ///
462 /// # Returns
463 ///
464 /// - `Ok(ThinCell<U>)` if the inner value is of type `U` and is not
465 /// currently borrowed
466 /// - `Err(DowncastError::Borrowed(self))` if the inner value is currently
467 /// borrowed
468 /// - `Err(DowncastError::Type(self))` if the inner value is not of type `U`
469 pub fn downcast<U: Any>(self) -> Result<ThinCell<U>, DowncastError<T>> {
470 let inner = self.inner();
471 if !inner.state.try_borrow() {
472 return Err(DowncastError::Borrowed(self));
473 }
474
475 // SAFETY: We have exclusive access via borrow flag.
476 let data_ref = unsafe { &*inner.data.get() };
477 let type_id = data_ref.type_id();
478 inner.state.unborrow();
479
480 if TypeId::of::<U>() == type_id {
481 // SAFETY: We have verified that the inner value is of type `U`
482 Ok(unsafe { self.downcast_unchecked::<U>() })
483 } else {
484 Err(DowncastError::Type(self))
485 }
486 }
487 }
488
489 /// `ThinCell` is `Unpin` as it does not move its inner data.
490 impl<T: ?Sized> Unpin for ThinCell<T> {}
491
492 impl<'a, T: ?Sized> Drop for Ref<'a, T> {
493 fn drop(&mut self) {
494 self.state.unborrow();
495 }
496 }
497
498 impl<'a, T: ?Sized> Deref for Ref<'a, T> {
499 type Target = T;
500
501 fn deref(&self) -> &T {
502 self.value
503 }
504 }
505
506 impl<'a, T: ?Sized> DerefMut for Ref<'a, T> {
507 fn deref_mut(&mut self) -> &mut T {
508 self.value
509 }
510 }
511
512 impl<'a, T: Debug + ?Sized> Debug for Ref<'a, T> {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 Debug::fmt(&**self, f)
515 }
516 }
517
518 impl<'a, T: Display + ?Sized> Display for Ref<'a, T> {
519 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520 Display::fmt(&**self, f)
521 }
522 }
523
524 impl<T: ?Sized> Clone for ThinCell<T> {
525 fn clone(&self) -> Self {
526 self.state().inc();
527
528 ThinCell {
529 ptr: self.ptr,
530 _marker: PhantomData,
531 }
532 }
533 }
534
535 #[cfg(not(feature = "weak"))]
536 impl<T: ?Sized> Drop for ThinCell<T> {
537 fn drop(&mut self) {
538 let inner = self.inner();
539 if !inner.state.dec() {
540 // Not last owner, nothing to do
541 return;
542 }
543
544 // SAFETY: We are the last owner, so we have unique ownership, and we're not
545 // using `self` after this call.
546 unsafe {
547 self.drop_in_place();
548 }
549 }
550 }
551
552 #[cfg(feature = "weak")]
553 impl<T: ?Sized> Drop for ThinCell<T> {
554 fn drop(&mut self) {
555 let inner = self.inner();
556 if !inner.state.dec() {
557 // Not last strong owner, nothing to do
558 return;
559 }
560
561 // Keep the strong side's collective weak ref alive as a real `Weak`
562 // guard so unwinding through `T::drop` still releases the allocation.
563 let _weak: Weak<T> = Weak {
564 ptr: self.ptr,
565 _marker: PhantomData,
566 };
567
568 // Drop the value in place.
569 // SAFETY: We are the last strong owner, so we have unique ownership.
570 unsafe {
571 std::ptr::drop_in_place(inner.data.get());
572 }
573 }
574 }
575
576 #[cfg(feature = "weak")]
577 impl<T: ?Sized> Weak<T> {
578 /// Reconstructs the raw pointer to the inner allocation.
579 fn inner_ptr(&self) -> *const Inner<T> {
580 let ptr = self.ptr.as_ptr();
581
582 if ThinCell::<T>::IS_SIZED {
583 // SIZED CASE: Cast pointer-to-pointer
584 let ptr_ref = &ptr as *const *mut () as *const *const Inner<T>;
585 unsafe { *ptr_ref }
586 } else {
587 // UNSIZED CASE: Read metadata
588 let metadata = unsafe { *(ptr as *const usize) };
589 FatPtr { ptr, metadata }.into_ptr()
590 }
591 }
592
593 /// Returns a reference to the inner allocation.
594 fn inner(&self) -> &Inner<T> {
595 unsafe { &*self.inner_ptr() }
596 }
597
598 /// Returns a reference to the state cell.
599 fn state(&self) -> &State {
600 &self.inner().state
601 }
602
603 /// Attempts to upgrade the weak reference to a strong reference.
604 ///
605 /// Returns `Some(ThinCell)` if the value still exists, or `None` if it
606 /// has been dropped.
607 ///
608 /// # Examples
609 ///
610 /// ```
611 /// # #[cfg(feature = "weak")]
612 /// # {
613 /// # use thin_cell::sync::ThinCell;
614 /// let cell = ThinCell::new(42);
615 /// let weak = cell.downgrade();
616 ///
617 /// let strong = weak.upgrade().unwrap();
618 /// assert_eq!(*strong.borrow(), 42);
619 ///
620 /// drop(cell);
621 /// drop(strong);
622 /// assert!(weak.upgrade().is_none());
623 /// # }
624 /// ```
625 pub fn upgrade(&self) -> Option<ThinCell<T>> {
626 let state = self.state();
627
628 // Atomically try to increment strong count only if non-zero
629 if !state.try_inc() {
630 return None;
631 }
632
633 Some(ThinCell {
634 ptr: self.ptr,
635 _marker: PhantomData,
636 })
637 }
638
639 /// Returns the number of strong references.
640 pub fn strong_count(&self) -> usize {
641 self.state().load().strong_count()
642 }
643
644 /// Returns the number of weak references.
645 pub fn weak_count(&self) -> usize {
646 self.state().load().weak_count()
647 }
648
649 /// Gets a raw pointer to the inner allocation.
650 ///
651 /// The pointer is valid only if the strong count is non-zero.
652 pub fn as_ptr(&self) -> *const () {
653 self.ptr.as_ptr()
654 }
655 }
656
657 #[cfg(feature = "weak")]
658 impl<T: ?Sized> Clone for Weak<T> {
659 fn clone(&self) -> Self {
660 self.state().inc_weak();
661 Weak {
662 ptr: self.ptr,
663 _marker: PhantomData,
664 }
665 }
666 }
667
668 #[cfg(feature = "weak")]
669 impl<T: ?Sized> Drop for Weak<T> {
670 fn drop(&mut self) {
671 let inner = self.inner();
672 if !inner.state.dec_weak() {
673 // Not last weak ref, nothing to do
674 return;
675 }
676
677 // Last weak ref and no strong refs - deallocate memory only
678 // The value T was already dropped when the last strong ref was dropped
679 // SAFETY: We are the last weak owner and no strong owners exist
680 unsafe {
681 let layout = std::alloc::Layout::for_value(inner);
682 std::alloc::dealloc(self.inner_ptr() as *mut u8, layout);
683 }
684 }
685 }
686
687 #[cfg(feature = "weak")]
688 impl<T: ?Sized> Debug for Weak<T> {
689 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
690 write!(f, "(Weak)")
691 }
692 }
693
694 impl<T: Default> Default for ThinCell<T> {
695 fn default() -> Self {
696 ThinCell::new(T::default())
697 }
698 }
699
700 impl<T: Debug + ?Sized> Debug for ThinCell<T> {
701 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
702 let inner = self.inner();
703 let state = inner.state.load();
704 let mut d = f.debug_struct("ThinCell");
705 match self.try_borrow() {
706 Some(borrowed) => d.field("value", &borrowed),
707 None => d.field("value", &"<borrowed>"),
708 }
709 .field("state", &state)
710 .finish()
711 }
712 }
713
714 impl<T: Display + ?Sized> Display for ThinCell<T> {
715 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
716 match self.try_borrow() {
717 Some(borrowed) => Display::fmt(&*borrowed, f),
718 None => write!(f, "<borrowed>"),
719 }
720 }
721 }
722
723 impl<T: PartialEq + ?Sized> PartialEq<ThinCell<T>> for ThinCell<T> {
724 /// Compares the inner values for equality.
725 ///
726 /// This will block on `sync` version or panic on `unsync` version if either `ThinCell` is currently borrowed.
727 ///
728 /// If a shallow comparison is desired, use [`ptr_eq`](ThinCell::ptr_eq)
729 /// instead.
730 fn eq(&self, other: &Self) -> bool {
731 self.borrow().eq(&other.borrow())
732 }
733 }
734
735 impl<T: Eq + ?Sized> Eq for ThinCell<T> {}
736
737 #[allow(clippy::non_canonical_partial_ord_impl)]
738 impl<T: Ord + ?Sized> PartialOrd<ThinCell<T>> for ThinCell<T> {
739 /// Compares the inner values.
740 ///
741 /// This will block on `sync` version or panic on `unsync` version if either `ThinCell` is currently borrowed.
742 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
743 self.borrow().partial_cmp(&other.borrow())
744 }
745 }
746
747 impl<T: Ord + ?Sized> Ord for ThinCell<T> {
748 /// Compares the inner values.
749 ///
750 /// This will block on `sync` version or panic on `unsync` version if either `ThinCell` is currently borrowed.
751 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
752 self.borrow().cmp(&other.borrow())
753 }
754 }
755 }
756}
757
758use thin_cell;