comparison rust/pyo3-sharedref/src/lib.rs @ 52633:d85514a88706

rust-pyo3-sharedref: reworked constructors We had previously duplicated the `new` associated function on `PySharedRef` with a method on `PySharedRefCell`: in `rust-cpython`, the former was hidden by the accessor defined by the `py_class!` macro, which we did not port yet. On `PySharedRefCell` itself, replacing the `new` associated function by the `From` trait carries all the needed semantics, and has the advantage of less repetititons of the type name, which will help with further refactorings and renamings.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Sun, 15 Dec 2024 14:42:53 +0100
parents be765f6797cc
children d1e304025b90
comparison
equal deleted inserted replaced
52632:a7d2529ed6dd 52633:d85514a88706
81 /// impl Set { 81 /// impl Set {
82 /// #[new] 82 /// #[new]
83 /// fn new(values: &Bound<'_, PyTuple>) -> PyResult<Self> { 83 /// fn new(values: &Bound<'_, PyTuple>) -> PyResult<Self> {
84 /// let as_vec = values.extract::<Vec<i32>>()?; 84 /// let as_vec = values.extract::<Vec<i32>>()?;
85 /// let s: HashSet<_> = as_vec.iter().copied().collect(); 85 /// let s: HashSet<_> = as_vec.iter().copied().collect();
86 /// Ok(Self { 86 /// Ok(Self { rust_set: s.into() })
87 /// rust_set: PySharedRefCell::new(s),
88 /// })
89 /// } 87 /// }
90 /// 88 ///
91 /// fn __iter__(slf: &Bound<'_, Self>) -> SetIterator { 89 /// fn __iter__(slf: &Bound<'_, Self>) -> SetIterator {
92 /// SetIterator::new(slf) 90 /// SetIterator::new(slf)
93 /// } 91 /// }
94 /// 92 ///
95 /// fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> { 93 /// fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> {
96 /// let rust_set = &slf.borrow().rust_set; 94 /// let rust_set = &slf.borrow().rust_set;
97 /// let shared_ref = unsafe { rust_set.borrow(slf) }; 95 /// let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
98 /// let mut set_ref = shared_ref.borrow_mut(); 96 /// let mut set_ref = shared_ref.borrow_mut();
99 /// set_ref.insert(i); 97 /// set_ref.insert(i);
100 /// Ok(()) 98 /// Ok(())
101 /// } 99 /// }
102 /// } 100 /// }
110 /// impl SetIterator { 108 /// impl SetIterator {
111 /// #[new] 109 /// #[new]
112 /// fn new(s: &Bound<'_, Set>) -> Self { 110 /// fn new(s: &Bound<'_, Set>) -> Self {
113 /// let py = s.py(); 111 /// let py = s.py();
114 /// let rust_set = &s.borrow().rust_set; 112 /// let rust_set = &s.borrow().rust_set;
115 /// let shared_ref = unsafe { rust_set.borrow(s) }; 113 /// let shared_ref = unsafe { rust_set.borrow_with_owner(s) };
116 /// let leaked_set = shared_ref.leak_immutable(); 114 /// let leaked_set = shared_ref.leak_immutable();
117 /// let iter = unsafe { leaked_set.map(py, |o| o.iter()) }; 115 /// let iter = unsafe { leaked_set.map(py, |o| o.iter()) };
118 /// Self { 116 /// Self {
119 /// rust_iter: iter.into(), 117 /// rust_iter: iter.into(),
120 /// } 118 /// }
174 state: PySharedState, 172 state: PySharedState,
175 data: RwLock<T>, 173 data: RwLock<T>,
176 } 174 }
177 175
178 impl<T> PySharedRefCell<T> { 176 impl<T> PySharedRefCell<T> {
179 /// Creates a new `PySharedRefCell` containing `value`.
180 pub fn new(value: T) -> PySharedRefCell<T> {
181 Self {
182 state: PySharedState::new(),
183 data: value.into(),
184 }
185 }
186
187 /// Borrows the shared data and its state, keeping a reference 177 /// Borrows the shared data and its state, keeping a reference
188 /// on the owner Python object. 178 /// on the owner Python object.
189 /// 179 ///
190 /// # Safety 180 /// # Safety
191 /// 181 ///
192 /// The `data` must be owned by the `owner`. Otherwise, calling 182 /// The `data` must be owned by the `owner`. Otherwise, calling
193 /// `leak_immutable()` on the shared ref would create an invalid reference. 183 /// `leak_immutable()` on the shared ref would create an invalid reference.
194 pub unsafe fn borrow<'py>( 184 pub unsafe fn borrow_with_owner<'py>(
195 &'py self, 185 &'py self,
196 owner: &'py Bound<'py, PyAny>, 186 owner: &'py Bound<'py, PyAny>,
197 ) -> PySharedRef<'py, T> { 187 ) -> PySharedRef<'py, T> {
198 PySharedRef { 188 PySharedRef {
199 owner, 189 owner,
201 data: &self.data, 191 data: &self.data,
202 } 192 }
203 } 193 }
204 } 194 }
205 195
196 impl<T> From<T> for PySharedRefCell<T> {
197 fn from(value: T) -> Self {
198 Self {
199 state: PySharedState::new(),
200 data: value.into(),
201 }
202 }
203 }
204
206 /// Errors that can happen in `leak_immutable()` 205 /// Errors that can happen in `leak_immutable()`
207 #[derive(Debug, PartialEq, Eq)] 206 #[derive(Debug, PartialEq, Eq)]
208 pub enum TryLeakError { 207 pub enum TryLeakError {
209 /// The inner lock is poisoned and we do not want to implement recovery 208 /// The inner lock is poisoned and we do not want to implement recovery
210 InnerLockPoisoned, 209 InnerLockPoisoned,
229 state: &'py PySharedState, 228 state: &'py PySharedState,
230 data: &'py RwLock<T>, // TODO perhaps this needs Pin 229 data: &'py RwLock<T>, // TODO perhaps this needs Pin
231 } 230 }
232 231
233 impl<'py, T: ?Sized> PySharedRef<'py, T> { 232 impl<'py, T: ?Sized> PySharedRef<'py, T> {
234 /// Creates a reference to the given `PySharedRefCell` owned by the
235 /// given `PyObject`.
236 ///
237 /// # Safety
238 ///
239 /// The `data` must be owned by the `owner`. Otherwise, `leak_immutable()`
240 /// would create an invalid reference.
241 #[doc(hidden)]
242 pub unsafe fn new(
243 owner: &'py Bound<'py, PyAny>,
244 data: &'py PySharedRefCell<T>,
245 ) -> Self {
246 Self {
247 owner,
248 state: &data.state,
249 data: &data.data,
250 }
251 }
252
253 /// Immutably borrows the wrapped value. 233 /// Immutably borrows the wrapped value.
254 /// 234 ///
255 /// # Panics 235 /// # Panics
256 /// 236 ///
257 /// Panics if the value is currently mutably borrowed. 237 /// Panics if the value is currently mutably borrowed.