annotate rust/pyo3-sharedref/src/lib.rs @ 52636:4a73eb3923ac

rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject Rationale: - the object itself is not unsafe, only most of its methods are. This is similar to raw pointers: obtaining them is not unsafe, using them is. That being said, we are not ready yet to declare, e.g, `borrow_with_owner()` safe because that gives an early warning to users. - it was not really a leak, as the data is actually owned by a Python object on which we keep a (Python) reference with proper increment of the refcount. Hence the terminology was too much of a deterrent. We hope that the new terminology conveys both that the data contains a shared reference and that it was generously lended by a Python object. The `SharedByPyObjectRef` name is arguably heavy, but it is merely an implementation detail that users will not be much exposed to, thanks to the `Deref` implementation. As previously, we keep the changes in tests to a minimum, to make obvious in the diff that the tests have not changed. We will take care of renaming their local variables and functions in a later move.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Sun, 15 Dec 2024 15:19:43 +0100
parents c25d345f5aa5
children a945845137b1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // Copyright (c) 2019 Raphaël Gomès <rgomes@octobus.net>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 // Yuya Nishihara <yuya@tcha.org>
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 // 2024 Georges Racinet <georges.racinet@cloudcrane.io>
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 // of this software and associated documentation files (the "Software"), to
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7 // deal in the Software without restriction, including without limitation the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 // sell copies of the Software, and to permit persons to whom the Software is
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10 // furnished to do so, subject to the following conditions:
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
11 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
12 // The above copyright notice and this permission notice shall be included in
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
13 // all copies or substantial portions of the Software.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
14 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
21 // IN THE SOFTWARE.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
22
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
23 //! Utility to share Rust reference across Python objects.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
24
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
25 use pyo3::exceptions::PyRuntimeError;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
26 use pyo3::prelude::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
27
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
28 use std::ops::{Deref, DerefMut};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
29 use std::sync::atomic::{AtomicUsize, Ordering};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
30 use std::sync::{
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
31 RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, TryLockResult,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
32 };
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
33
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
34 /// A mutable memory location shareable immutably across Python objects.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
35 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
36 /// This data structure is meant to be used as a field in a Python class
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
37 /// definition.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
38 /// It provides interior mutability in a way that allows it to be immutably
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
39 /// referenced by other Python objects defined in Rust than its owner, in
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
40 /// a more general form than references to the whole data.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
41 /// These immutable references are stored in the referencing Python objects as
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
42 /// [`SharedByPyObject`] fields.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
43 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
44 /// The primary use case is to implement a Python iterator over a Rust
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
45 /// iterator: since a Python object cannot hold a lifetime-bound object,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
46 /// `Iter<'a, T>` cannot be a data field of the Python iterator object.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
47 /// While `&'a T` can be replaced with [`std::sync::Arc`], this is typically
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
48 /// not suited for more complex objects that are created from such references
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
49 /// and re-expose the lifetime on their types, such as iterators.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
50 /// The [`PyShareableRef::share_immutable()`] and
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
51 /// [`SharedByPyObject::map()`] methods provide a way around this issue.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
52 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
53 /// [`PyShareable`] is [`Sync`]. It works internally with locks and
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
54 /// a "generation" counter that keeps track of mutations.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
55 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
56 /// [`PyShareable`] is merely a data struct to be stored in its
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
57 /// owner Python object.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
58 /// Any further operation will be performed through [`PyShareableRef`], which
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
59 /// is a lifetime-bound reference to the [`PyShareable`].
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
60 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
61 /// # Example
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
62 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
63 /// ```
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
64 /// use pyo3::prelude::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
65 /// use pyo3_sharedref::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
66 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
67 /// use pyo3::ffi::c_str;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
68 /// use pyo3::types::PyDictMethods;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
69 /// use pyo3::types::{PyDict, PyTuple};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
70 /// use std::collections::{hash_set::Iter as IterHashSet, HashSet};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
71 /// use pyo3::exceptions::PyRuntimeError;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
72 /// use std::ffi::CStr;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
73 /// use std::vec::Vec;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
74 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
75 /// #[pyclass(sequence)]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
76 /// struct Set {
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
77 /// rust_set: PyShareable<HashSet<i32>>,
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
78 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
79 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
80 /// #[pymethods]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
81 /// impl Set {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
82 /// #[new]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
83 /// fn new(values: &Bound<'_, PyTuple>) -> PyResult<Self> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
84 /// let as_vec = values.extract::<Vec<i32>>()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
85 /// let s: HashSet<_> = as_vec.iter().copied().collect();
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
86 /// Ok(Self { rust_set: s.into() })
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
87 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
88 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
89 /// fn __iter__(slf: &Bound<'_, Self>) -> SetIterator {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
90 /// SetIterator::new(slf)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
91 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
92 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
93 /// fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
94 /// let rust_set = &slf.borrow().rust_set;
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
95 /// let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
96 /// let mut set_ref = shared_ref.write();
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
97 /// set_ref.insert(i);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
98 /// Ok(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
99 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
100 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
101 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
102 /// #[pyclass]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
103 /// struct SetIterator {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
104 /// rust_iter: SharedByPyObject<IterHashSet<'static, i32>>,
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
105 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
106 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
107 /// #[pymethods]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
108 /// impl SetIterator {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
109 /// #[new]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
110 /// fn new(s: &Bound<'_, Set>) -> Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
111 /// let py = s.py();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
112 /// let rust_set = &s.borrow().rust_set;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
113 /// let shareable_ref = unsafe { rust_set.borrow_with_owner(s) };
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
114 /// let shared_set = shareable_ref.share_immutable();
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
115 /// let iter = unsafe { shared_set.map(py, |o| o.iter()) };
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
116 /// Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
117 /// rust_iter: iter.into(),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
118 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
119 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
120 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
121 /// fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
122 /// slf
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
123 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
124 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
125 /// fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult<Option<i32>> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
126 /// let py = slf.py();
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
127 /// let shared = &mut slf.rust_iter;
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
128 /// let mut inner = unsafe { shared.try_borrow_mut(py) }?;
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
129 /// Ok(inner.next().copied())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
130 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
131 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
132 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
133 /// /// a shortcut similar to `[pyo3::py_run!]`, allowing inspection of PyErr
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
134 /// fn py_run(statement: &CStr, locals: &Bound<'_, PyDict>) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
135 /// locals.py().run(statement, None, Some(locals))
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
136 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
137 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
138 /// # pyo3::prepare_freethreaded_python();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
139 /// Python::with_gil(|py| {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
140 /// let tuple = PyTuple::new(py, vec![2, 1, 2])?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
141 /// let set = Bound::new(py, Set::new(&tuple)?)?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
142 /// let iter = Bound::new(py, Set::__iter__(&set))?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
143 /// let locals = PyDict::new(py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
144 /// locals.set_item("rust_set", set).unwrap();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
145 /// locals.set_item("rust_iter", iter).unwrap();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
146 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
147 /// /// iterating on our Rust set just works
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
148 /// py_run(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
149 /// c_str!("assert sorted(i for i in rust_iter) == [1, 2]"),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
150 /// &locals,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
151 /// )?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
152 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
153 /// /// however, if any mutation occurs on the Rust set, the iterator
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
154 /// /// becomes invalid. Attempts to use it raise `RuntimeError`.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
155 /// py_run(c_str!("rust_set.add(3)"), &locals)?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
156 /// let err = py_run(c_str!("next(rust_iter)"), &locals).unwrap_err();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
157 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
158 /// let exc_repr = format!("{:?}", err.value(py));
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
159 /// assert_eq!(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
160 /// exc_repr,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
161 /// "RuntimeError('Cannot access to shared reference after mutation')"
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
162 /// );
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
163 /// # Ok::<(), PyErr>(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
164 /// })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
165 /// # .expect("This example should not return an error");
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
166 /// ```
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
167 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
168 /// The borrow rules are enforced dynamically in a similar manner to the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
169 /// Python iterator.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
170 ///
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
171 /// [`PyShareable`] is merely a data struct to be stored in a Python object.
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
172 /// Any further operation will be performed through [PyShareableRef], which is
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
173 /// a lifetime-bound reference to the [`PyShareable`].
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
174 #[derive(Debug)]
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
175 pub struct PyShareable<T: ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
176 state: PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
177 data: RwLock<T>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
178 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
179
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
180 impl<T> PyShareable<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
181 /// Borrows the shared data and its state, keeping a reference
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
182 /// on the owner Python object.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
183 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
184 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
185 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
186 /// The `data` must be owned by the `owner`. Otherwise, calling
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
187 /// `share_immutable()` on the shared ref would create an invalid
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
188 /// reference.
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
189 pub unsafe fn borrow_with_owner<'py>(
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
190 &'py self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
191 owner: &'py Bound<'py, PyAny>,
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
192 ) -> PyShareableRef<'py, T> {
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
193 PyShareableRef {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
194 owner,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
195 state: &self.state,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
196 data: &self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
197 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
198 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
199 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
200
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
201 impl<T> From<T> for PyShareable<T> {
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
202 fn from(value: T) -> Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
203 Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
204 state: PySharedState::new(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
205 data: value.into(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
206 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
207 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
208 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
209
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
210 /// Errors that can happen in `share_immutable()`
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
211 #[derive(Debug, PartialEq, Eq)]
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
212 pub enum TryShareError {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
213 /// The inner lock is poisoned and we do not want to implement recovery
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
214 InnerLockPoisoned,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
215 /// The inner lock would block and we are expecting to take it immediately
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
216 InnerLockWouldBlock,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
217 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
218
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
219 impl<T> From<TryLockError<T>> for TryShareError {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
220 fn from(e: TryLockError<T>) -> Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
221 match e {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
222 TryLockError::Poisoned(_) => Self::InnerLockPoisoned,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
223 TryLockError::WouldBlock => Self::InnerLockWouldBlock,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
224 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
225 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
226 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
227
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
228 /// A reference to [`PyShareable`] and its legit owner Python object.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
229 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
230 /// This is a lifetime-bound reference to the [PyShareable] data field,
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
231 /// and could be created by an automatically generated accessor when
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
232 /// we make one.
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
233 pub struct PyShareableRef<'py, T: 'py + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
234 owner: &'py Bound<'py, PyAny>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
235 state: &'py PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
236 data: &'py RwLock<T>, // TODO perhaps this needs Pin
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
237 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
238
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
239 impl<'py, T: ?Sized> PyShareableRef<'py, T> {
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
240 /// Take the lock on the wrapped value for read-only operations.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
241 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
242 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
243 ///
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
244 /// Panics if the lock is currently held for write operations.
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
245 pub fn read(&self) -> RwLockReadGuard<'py, T> {
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
246 self.try_read().expect("already mutably borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
247 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
248
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
249 /// Immutably borrows the wrapped value, returning an error if the value
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
250 /// is currently mutably borrowed.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
251 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'py, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
252 // state isn't involved since
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
253 // - data.try_read() would fail if self is mutably borrowed,
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
254 // - and data.try_write() would fail while self is borrowed.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
255 self.data.try_read()
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
256 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
257
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
258 /// Take the lock on the wrapped value for write operations.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
259 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
260 /// Any existing shared references will be invalidated.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
261 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
262 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
263 ///
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
264 /// Panics if the lock is currently held.
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
265 pub fn write(&self) -> RwLockWriteGuard<'py, T> {
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
266 self.try_write().expect("already borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
267 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
268
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
269 /// Mutably borrows the wrapped value, returning an error if the value
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
270 /// is currently borrowed.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
271 pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
272 // the value may be immutably borrowed through SharedByPyObject
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
273 if self.state.current_borrow_count(self.py()) > 0 {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
274 // propagate borrow-by-shared state to data to get BorrowMutError
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
275 let _dummy = self.data.read();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
276 let _unused = self.data.try_write()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
277 unreachable!("BorrowMutError should have been returned");
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
278 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
279
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
280 let data_ref = self.data.try_write()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
281 self.state.increment_generation(self.py());
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
282 Ok(data_ref)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
283 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
284
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
285 /// Creates an immutable reference which is not bound to lifetime.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
286 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
287 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
288 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
289 /// Panics if the value is currently mutably borrowed.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
290 pub fn share_immutable(&self) -> SharedByPyObject<&'static T> {
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
291 self.try_share_immutable()
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
292 .expect("already mutably borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
293 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
294
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
295 /// Creates an immutable reference which is not bound to lifetime,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
296 /// returning an error if the value is currently mutably borrowed.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
297 pub fn try_share_immutable(
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
298 &self,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
299 ) -> Result<SharedByPyObject<&'static T>, TryShareError> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
300 // make sure self.data isn't mutably borrowed; otherwise the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
301 // generation number wouldn't be trusted.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
302 let data_ref = self.try_read()?;
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
303
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
304 // keep reference to the owner so the data and state are alive,
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
305 // but the data pointer can be invalidated by write().
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
306 // the state wouldn't since it is immutable.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
307 let state_ptr: *const PySharedState = self.state;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
308 let data_ptr: *const T = &*data_ref;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
309 Ok(SharedByPyObject::<&'static T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
310 owner: self.owner.clone().unbind(),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
311 state: unsafe { &*state_ptr },
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
312 generation: self.state.current_generation(self.py()),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
313 data: unsafe { &*data_ptr },
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
314 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
315 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
316
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
317 /// Retrieve the GIL handle
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
318 fn py(&self) -> Python<'py> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
319 // Since this is a smart pointer implying the GIL lifetime,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
320 // we might as well use `assume_gil_acquired`, but the method
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
321 // of `Bound` does it for us.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
322 self.owner.py()
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
323 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
324 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
325
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
326 /// The shared state between Python and Rust
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
327 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
328 /// `PySharedState` is owned by `PyShareable`, and is shared across its
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
329 /// derived references. The consistency of these references are guaranteed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
330 /// as follows:
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
331 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
332 /// - The immutability of `PycCass` object fields. Any mutation of
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
333 /// [`PyShareable`] is allowed only through its `write()`.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
334 /// - The `py: Python<'_>` token, which makes sure that any data access is
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
335 /// synchronized by the GIL.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
336 /// - The underlying `RefCell`, which prevents `PyShareable` value from being
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
337 /// directly borrowed or shared while it is mutably borrowed.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
338 /// - The `borrow_count`, which is the number of references borrowed from
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
339 /// `SharedByPyObject`. Just like `RefCell`, mutation is prohibited while
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
340 /// `SharedByPyObject` is borrowed.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
341 /// - The `generation` counter, which increments on `write()`.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
342 /// `SharedByPyObject`
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
343 #[derive(Debug)]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
344 struct PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
345 // The counter variable could be Cell<usize> since any operation on
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
346 // PySharedState is synchronized by the GIL, but being "atomic" makes
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
347 // PySharedState inherently Sync. The ordering requirement doesn't
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
348 // matter thanks to the GIL. That's why Ordering::Relaxed is used
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
349 // everywhere.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
350 /// The number of immutable references borrowed through shared reference.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
351 borrow_count: AtomicUsize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
352 /// The mutation counter of the underlying value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
353 generation: AtomicUsize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
354 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
355
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
356 impl PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
357 const fn new() -> PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
358 PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
359 borrow_count: AtomicUsize::new(0),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
360 generation: AtomicUsize::new(0),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
361 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
362 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
363
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
364 fn current_borrow_count(&self, _py: Python) -> usize {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
365 self.borrow_count.load(Ordering::Relaxed)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
366 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
367
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
368 fn increase_borrow_count(&self, _py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
369 // this wraps around if there are more than usize::MAX borrowed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
370 // references, which shouldn't happen due to memory limit.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
371 self.borrow_count.fetch_add(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
372 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
373
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
374 fn decrease_borrow_count(&self, _py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
375 let prev_count = self.borrow_count.fetch_sub(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
376 assert!(prev_count > 0);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
377 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
378
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
379 fn current_generation(&self, _py: Python) -> usize {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
380 self.generation.load(Ordering::Relaxed)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
381 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
382
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
383 fn increment_generation(&self, py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
384 assert_eq!(self.current_borrow_count(py), 0);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
385 // this wraps around to the same value if mutably borrowed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
386 // usize::MAX times, which wouldn't happen in practice.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
387 self.generation.fetch_add(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
388 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
389 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
390
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
391 /// Helper to keep the borrow count updated while the shared object is
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
392 /// immutably borrowed without using the `RwLock` interface.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
393 struct BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
394 py: Python<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
395 state: &'a PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
396 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
397
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
398 impl<'a> BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
399 fn new(py: Python<'a>, state: &'a PySharedState) -> BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
400 state.increase_borrow_count(py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
401 BorrowPyShared { py, state }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
402 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
403 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
404
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
405 impl<'a> Drop for BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
406 fn drop(&mut self) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
407 self.state.decrease_borrow_count(self.py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
408 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
409 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
410
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
411 /// An immutable reference to [`PyShareable`] value, not bound to lifetime.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
412 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
413 /// The reference will be invalidated once the original value is mutably
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
414 /// borrowed.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
415 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
416 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
417 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
418 /// Even though [`SharedByPyObject`] tries to enforce the real lifetime of the
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
419 /// underlying object, the object having the artificial `'static` lifetime
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
420 /// may be exposed to your Rust code. You must be careful to not make a bare
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
421 /// reference outlive the actual object lifetime.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
422 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
423 /// TODO this first example would not compile if [`SharedByPyObject::map()`]
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
424 /// would only accept [`Fn`] instead of [`FnOnce`].
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
425 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
426 /// ```ignore
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
427 /// let outer;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
428 /// unsafe { shared.map(py, |o| { outer = o }) }; // Bad
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
429 /// ```
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
430 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
431 /// ```ignore
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
432 /// let outer;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
433 /// let mut shared_iter = shared.map(py, |o| o.iter());
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
434 /// {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
435 /// let mut iter = unsafe { shared_iter.try_borrow_mut(py) };
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
436 /// let inner = iter.next(); // Good, in borrow scope
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
437 /// outer = inner; // Bad, &'static T may outlive
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
438 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
439 /// ```
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
440 pub struct SharedByPyObject<T: ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
441 owner: PyObject,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
442 state: &'static PySharedState,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
443 /// Generation counter of data `T` captured when SharedByPyObject is
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
444 /// created.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
445 generation: usize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
446 /// Underlying data of artificial lifetime, which is valid only when
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
447 /// state.generation == self.generation.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
448 data: T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
449 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
450
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
451 // DO NOT implement Deref for SharedByPyObject<T>! Dereferencing
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
452 // SharedByPyObject without taking Python GIL wouldn't be safe. Also, the
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
453 // underling reference is invalid if generation != state.generation.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
454
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
455 impl<T: ?Sized> SharedByPyObject<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
456 // No panicking version of borrow() and borrow_mut() are implemented
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
457 // because the underlying value is supposed to be mutated in Python
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
458 // world, and the Rust library designer can't prevent it.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
459
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
460 // try_borrow() and try_borrow_mut() are unsafe because self.data may
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
461 // have a function returning the inner &'static reference.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
462 // If T is &'static U, its lifetime can be easily coerced to &'a U, but
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
463 // how could we do that for Whatever<'static> in general?
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
464
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
465 /// Immutably borrows the wrapped value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
466 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
467 /// Borrowing fails if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
468 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
469 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
470 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
471 /// The lifetime of the innermost object is artificial. Do not obtain and
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
472 /// copy it out of the borrow scope.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
473 pub unsafe fn try_borrow<'a>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
474 &'a self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
475 py: Python<'a>,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
476 ) -> PyResult<SharedByPyObjectRef<'a, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
477 self.validate_generation(py)?;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
478 Ok(SharedByPyObjectRef {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
479 _borrow: BorrowPyShared::new(py, self.state),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
480 data: &self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
481 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
482 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
483
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
484 /// Mutably borrows the wrapped value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
485 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
486 /// Borrowing fails if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
487 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
488 /// Typically `T` is an iterator. If `T` is an immutable reference,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
489 /// `get_mut()` is useless since the inner value can't be mutated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
490 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
491 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
492 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
493 /// The lifetime of the innermost object is artificial. Do not obtain and
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
494 /// copy it out of the borrow scope.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
495 pub unsafe fn try_borrow_mut<'a>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
496 &'a mut self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
497 py: Python<'a>,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
498 ) -> PyResult<SharedByPyObjectRefMut<'a, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
499 self.validate_generation(py)?;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
500 Ok(SharedByPyObjectRefMut {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
501 _borrow: BorrowPyShared::new(py, self.state),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
502 data: &mut self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
503 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
504 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
505
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
506 fn validate_generation(&self, py: Python) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
507 if self.state.current_generation(py) == self.generation {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
508 Ok(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
509 } else {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
510 Err(PyRuntimeError::new_err(
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
511 "Cannot access to shared reference after mutation",
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
512 ))
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
513 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
514 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
515 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
516
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
517 impl<T> SharedByPyObject<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
518 /// Converts the inner value by the given function.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
519 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
520 /// Typically `T` is a static reference to a collection, and `U` is an
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
521 /// iterator of that collection.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
522 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
523 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
524 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
525 /// Panics if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
526 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
527 /// This is typically called immediately after the `SharedByPyObject` is
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
528 /// obtained. At this time, the reference must be valid and no panic
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
529 /// would occur.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
530 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
531 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
532 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
533 /// The lifetime of the object passed in to the function `f` is artificial.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
534 /// It's typically a static reference, but is valid only while the
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
535 /// corresponding `SharedByPyObject` is alive. Do not copy it out of the
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
536 /// function call.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
537 /// TODO would it be safe with `f: impl Fn(T) -> U` then?
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
538 pub unsafe fn map<U>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
539 self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
540 py: Python,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
541 f: impl FnOnce(T) -> U,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
542 ) -> SharedByPyObject<U> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
543 // Needs to test the generation value to make sure self.data reference
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
544 // is still intact.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
545 self.validate_generation(py)
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
546 .expect("map() over invalidated shared reference");
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
547
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
548 // f() could make the self.data outlive. That's why map() is unsafe.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
549 // In order to make this function safe, maybe we'll need a way to
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
550 // temporarily restrict the lifetime of self.data and translate the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
551 // returned object back to Something<'static>.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
552 let new_data = f(self.data);
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
553 SharedByPyObject {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
554 owner: self.owner,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
555 state: self.state,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
556 generation: self.generation,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
557 data: new_data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
558 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
559 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
560 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
561
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
562 /// An immutably borrowed reference to a shared value.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
563 pub struct SharedByPyObjectRef<'a, T: 'a + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
564 _borrow: BorrowPyShared<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
565 data: &'a T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
566 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
567
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
568 impl<'a, T: ?Sized> Deref for SharedByPyObjectRef<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
569 type Target = T;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
570
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
571 fn deref(&self) -> &T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
572 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
573 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
574 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
575
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
576 /// A mutably borrowed reference to a shared value.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
577 pub struct SharedByPyObjectRefMut<'a, T: 'a + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
578 _borrow: BorrowPyShared<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
579 data: &'a mut T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
580 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
581
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
582 impl<'a, T: ?Sized> Deref for SharedByPyObjectRefMut<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
583 type Target = T;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
584
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
585 fn deref(&self) -> &T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
586 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
587 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
588 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
589
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
590 impl<'a, T: ?Sized> DerefMut for SharedByPyObjectRefMut<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
591 fn deref_mut(&mut self) -> &mut T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
592 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
593 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
594 }