blob: 440a6c9399a82a68ca8f952e3fc649196489e234 [file] [log] [blame]
Joel Galenson2370d122020-10-12 16:02:26 -07001//! Traits for describing strong and weak pointers and their use as elements and keys.
2//!
3//! These traits provide mechanisms for converting between weak and strong pointers
4//! ([`WeakElement`](trait.WeakElement.html)) and for dereferencing strong pointers
5//! ([`WeakKey`](trait.WeakKey.html)). Implementations of these traits are provided for
6//! `std::rc::Weak` and `std::sync::Weak`. If you would like to use your own pointer type
7//! as a weak element, you need to implement `WeakElement` for your weak pointer type; to use it
8//! as a weak key, implement `WeakKey` as well.
9
10use std::hash::Hash;
11use std::{rc, sync};
12
13/// Interface for elements that can be stored in weak hash tables.
14///
15/// This trait applies to the weak version of a reference-counted pointer; it can be used to
16/// convert a weak pointer into a strong pointer and back. For example, the impl for
17/// `std::rc::Weak<T>` defines the `Strong` associated type as `std::rc::Rc<T>`. Then method
18/// `new` can be used to downgrade an `Rc<T>` to a `Weak<T>`, and method `view` can be used to
19/// upgrade a `Weak<T>` into an `Rc<T>`, if it's still alive. If we think of the weak pointer as
20/// what is stored, then the strong pointer is a temporary view of it.
21pub trait WeakElement {
22 /// The type at which a weak element can be viewed.
23 ///
24 /// For example, for `std::rc::Weak<T>`, this will be `std::rc::Rc<T>`.
25 type Strong;
26
27 /// Constructs a weak pointer from a strong pointer.
28 ///
29 /// This is usually implemented by a `downgrade` method.
30 fn new(view: &Self::Strong) -> Self;
31
32 /// Acquires a strong pointer from a weak pointer.
33 ///
34 /// This is usually implemented by an `upgrade` method.
35 fn view(&self) -> Option<Self::Strong>;
36
37 /// Is the given weak element expired?
38 ///
39 /// The default implemention checks whether a strong pointer can be obtained via `view`.
40 fn is_expired(&self) -> bool {
41 self.view().is_none()
42 }
43
44 /// Clones a strong pointer.
45 ///
46 /// The default implementation uses `new` and `view`; you should override it.
47 fn clone(view: &Self::Strong) -> Self::Strong
48 where Self: Sized
49 {
50 Self::new(view).view().expect("WeakElement::clone")
51 }
52}
53
54/// Interface for elements that can act as keys in weak hash tables.
55///
56/// To use an element as a weak hash map key or weak hash set element), the hash table
57/// needs to be able to view the actual key values to hash and compare them. This trait
58/// provides the necessary mechanism.
59pub trait WeakKey : WeakElement {
60 /// The underlying key type.
61 ///
62 /// For example, for `std::rc::Weak<T>`, this will be `T`.
63 type Key: ?Sized + Eq + Hash;
64
65 /// Allows borrowing a view of the key, via a callback.
66 ///
67 /// Rather than returning a borrowed reference to the actual key, this method passes a
68 /// reference to the key to a callback with an implicit higher-order lifetime bound. This is
69 /// necessary to get the lifetimes right in cases where the key is not actually store in the
70 /// strong pointer.
71 fn with_key<F, R>(view: &Self::Strong, f: F) -> R
72 where F: FnOnce(&Self::Key) -> R;
73}
74
75impl<T: ?Sized> WeakElement for rc::Weak<T> {
76 type Strong = rc::Rc<T>;
77
78 fn new(view: &Self::Strong) -> Self {
79 rc::Rc::<T>::downgrade(view)
80 }
81
82 fn view(&self) -> Option<Self::Strong> {
83 self.upgrade()
84 }
85
86 fn clone(view: &Self::Strong) -> Self::Strong {
87 view.clone()
88 }
89}
90
91impl<T: ?Sized + Eq + Hash> WeakKey for rc::Weak<T> {
92 type Key = T;
93
94 fn with_key<F, R>(view: &Self::Strong, f: F) -> R
95 where F: FnOnce(&Self::Key) -> R
96 {
97 f(&view)
98 }
99}
100
101impl<T: ?Sized> WeakElement for sync::Weak<T> {
102 type Strong = sync::Arc<T>;
103
104 fn new(view: &Self::Strong) -> Self {
105 sync::Arc::<T>::downgrade(view)
106 }
107
108 fn view(&self) -> Option<Self::Strong> {
109 self.upgrade()
110 }
111
112 fn clone(view: &Self::Strong) -> Self::Strong {
113 view.clone()
114 }
115}
116
117impl<T: ?Sized + Eq + Hash> WeakKey for sync::Weak<T>
118{
119 type Key = T;
120
121 fn with_key<F, R>(view: &Self::Strong, f: F) -> R
122 where F: FnOnce(&Self::Key) -> R
123 {
124 f(&view)
125 }
126}
127