Mercurial > public > mercurial-scm > hg
annotate rust/pyo3-sharedref/src/lib.rs @ 52610:c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
There were two problems with the naming:
- the PyO3 version is not based on `RefCell`. Rather than calling
this `SomethingRwLock` we decided it was best to consider this
an implementation detail. We mentioned it in the doc earlier on,
but that is merely just bringing some reassuring context to the
reader, not intended to be a needed structural explanation.
- the data is not shared: it is ready to be shared
To keep the changeset readable, we only make the very minimal changes
to the tests to make them pass, i.e., not renaming local variables
(this will be done in a later move).
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Sun, 15 Dec 2024 15:03:27 +0100 |
parents | d1e304025b90 |
children | 4a73eb3923ac |
rev | line source |
---|---|
52606
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 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
42 /// [`UnsafePyLeaked`] fields. |
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. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
50 /// The [`PyShareableRef::leak_immutable()`] and [`UnsafePyLeaked::map()`] |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
51 /// methods provide a way around this issue. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
52 /// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
53 /// [`PyShareable`] is [`Sync`]. It works internally with locks and |
52606
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 /// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
56 /// [`PyShareable`] is merely a data struct to be stored in its |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
57 /// owner Python object. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
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:
52609
diff
changeset
|
59 /// is a lifetime-bound reference to the [`PyShareable`]. |
52606
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 { |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
77 /// rust_set: PyShareable<HashSet<i32>>, |
52606
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(); |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
86 /// Ok(Self { rust_set: s.into() }) |
52606
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; |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
95 /// let shared_ref = unsafe { rust_set.borrow_with_owner(slf) }; |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
96 /// let mut set_ref = shared_ref.write(); |
52606
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 { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
104 /// rust_iter: UnsafePyLeaked<IterHashSet<'static, i32>>, |
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; |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
113 /// let shared_ref = unsafe { rust_set.borrow_with_owner(s) }; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
114 /// let leaked_set = shared_ref.leak_immutable(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
115 /// let iter = unsafe { leaked_set.map(py, |o| o.iter()) }; |
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(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
127 /// let leaked = &mut slf.rust_iter; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
128 /// let mut inner = unsafe { leaked.try_borrow_mut(py) }?; |
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, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
161 /// "RuntimeError('Cannot access to leaked reference after mutation')" |
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. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
170 /// |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
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:
52609
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:
52609
diff
changeset
|
173 /// a lifetime-bound reference to the [`PyShareable`]. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
174 #[derive(Debug)] |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
175 pub struct PyShareable<T: ?Sized> { |
52606
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 |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
180 impl<T> PyShareable<T> { |
52606
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 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
187 /// `leak_immutable()` on the shared ref would create an invalid reference. |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
188 pub unsafe fn borrow_with_owner<'py>( |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
189 &'py self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
190 owner: &'py Bound<'py, PyAny>, |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
191 ) -> PyShareableRef<'py, T> { |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
192 PyShareableRef { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
193 owner, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
194 state: &self.state, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
195 data: &self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
196 } |
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 |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
200 impl<T> From<T> for PyShareable<T> { |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
201 fn from(value: T) -> Self { |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
202 Self { |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
203 state: PySharedState::new(), |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
204 data: value.into(), |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
205 } |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
206 } |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
207 } |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
208 |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
209 /// Errors that can happen in `leak_immutable()` |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
210 #[derive(Debug, PartialEq, Eq)] |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
211 pub enum TryLeakError { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
212 /// 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
|
213 InnerLockPoisoned, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
214 /// 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
|
215 InnerLockWouldBlock, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
216 } |
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 impl<T> From<TryLockError<T>> for TryLeakError { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
219 fn from(e: TryLockError<T>) -> Self { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
220 match e { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
221 TryLockError::Poisoned(_) => Self::InnerLockPoisoned, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
222 TryLockError::WouldBlock => Self::InnerLockWouldBlock, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
223 } |
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 |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
227 /// A reference to [`PyShareable`] and its legit owner Python object. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
228 /// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
229 /// 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:
52609
diff
changeset
|
230 /// 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:
52609
diff
changeset
|
231 /// we make one. |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
232 pub struct PyShareableRef<'py, T: 'py + ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
233 owner: &'py Bound<'py, PyAny>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
234 state: &'py PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
235 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
|
236 } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
237 |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
238 impl<'py, T: ?Sized> PyShareableRef<'py, T> { |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
239 /// Take the lock on the wrapped value for read-only operations. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
240 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
241 /// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
242 /// |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
243 /// 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:
52608
diff
changeset
|
244 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:
52608
diff
changeset
|
245 self.try_read().expect("already mutably borrowed") |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
246 } |
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 /// 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
|
249 /// is currently mutably borrowed. |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
250 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'py, T>> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
251 // state isn't involved since |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
252 // - 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:
52608
diff
changeset
|
253 // - and data.try_write() would fail while self is borrowed. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
254 self.data.try_read() |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
255 } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
256 |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
257 /// Take the lock on the wrapped value for write operations. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
258 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
259 /// Any existing leaked references will be invalidated. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
260 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
261 /// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
262 /// |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
263 /// 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:
52608
diff
changeset
|
264 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:
52608
diff
changeset
|
265 self.try_write().expect("already borrowed") |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
266 } |
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 /// 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
|
269 /// is currently borrowed. |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
270 pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
271 // the value may be immutably borrowed through UnsafePyLeaked |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
272 if self.state.current_borrow_count(self.py()) > 0 { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
273 // propagate borrow-by-leaked state to data to get BorrowMutError |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
274 let _dummy = self.data.read(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
275 let _unused = self.data.try_write()?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
276 unreachable!("BorrowMutError should have been returned"); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
277 } |
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 let data_ref = self.data.try_write()?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
280 self.state.increment_generation(self.py()); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
281 Ok(data_ref) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
282 } |
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 /// 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
|
285 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
286 /// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
287 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
288 /// Panics if the value is currently mutably borrowed. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
289 pub fn leak_immutable(&self) -> UnsafePyLeaked<&'static T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
290 self.try_leak_immutable().expect("already mutably borrowed") |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
291 } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
292 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
293 /// 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
|
294 /// returning an error if the value is currently mutably borrowed. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
295 pub fn try_leak_immutable( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
296 &self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
297 ) -> Result<UnsafePyLeaked<&'static T>, TryLeakError> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
298 // 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
|
299 // generation number wouldn't be trusted. |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
300 let data_ref = self.try_read()?; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
301 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
302 // keep reference to the owner so the data and state are alive, |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
303 // but the data pointer can be invalidated by write(). |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
304 // the state wouldn't since it is immutable. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
305 let state_ptr: *const PySharedState = self.state; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
306 let data_ptr: *const T = &*data_ref; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
307 Ok(UnsafePyLeaked::<&'static T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
308 owner: self.owner.clone().unbind(), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
309 state: unsafe { &*state_ptr }, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
310 generation: self.state.current_generation(self.py()), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
311 data: unsafe { &*data_ptr }, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
312 }) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
313 } |
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 /// Retrieve the GIL handle |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
316 fn py(&self) -> Python<'py> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
317 // 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
|
318 // 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
|
319 // of `Bound` does it for us. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
320 self.owner.py() |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
321 } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
322 } |
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 /// The shared state between Python and Rust |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
325 /// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
326 /// `PySharedState` is owned by `PyShareable`, and is shared across its |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
327 /// 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
|
328 /// as follows: |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
329 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
330 /// - The immutability of `PycCass` object fields. Any mutation of |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
331 /// [`PyShareable`] is allowed only through its `write()`. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
332 /// - 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
|
333 /// synchronized by the GIL. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
334 /// - The underlying `RefCell`, which prevents `PyShareable` value from being |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
335 /// directly borrowed or leaked while it is mutably borrowed. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
336 /// - The `borrow_count`, which is the number of references borrowed from |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
337 /// `UnsafePyLeaked`. Just like `RefCell`, mutation is prohibited while |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
338 /// `UnsafePyLeaked` is borrowed. |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
339 /// - The `generation` counter, which increments on `write()`. `UnsafePyLeaked` |
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
340 /// reference is valid only if the `current_generation()` equals to the |
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
341 /// `generation` at the time of `leak_immutable()`. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
342 #[derive(Debug)] |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
343 struct PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
344 // 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
|
345 // 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
|
346 // PySharedState inherently Sync. The ordering requirement doesn't |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
347 // 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
|
348 // everywhere. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
349 /// The number of immutable references borrowed through leaked reference. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
350 borrow_count: AtomicUsize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
351 /// The mutation counter of the underlying value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
352 generation: AtomicUsize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
353 } |
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 impl PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
356 const fn new() -> PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
357 PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
358 borrow_count: AtomicUsize::new(0), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
359 generation: AtomicUsize::new(0), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
360 } |
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 fn current_borrow_count(&self, _py: Python) -> usize { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
364 self.borrow_count.load(Ordering::Relaxed) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
365 } |
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 fn increase_borrow_count(&self, _py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
368 // 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
|
369 // 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
|
370 self.borrow_count.fetch_add(1, Ordering::Relaxed); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
371 } |
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 fn decrease_borrow_count(&self, _py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
374 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
|
375 assert!(prev_count > 0); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
376 } |
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 fn current_generation(&self, _py: Python) -> usize { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
379 self.generation.load(Ordering::Relaxed) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
380 } |
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 fn increment_generation(&self, py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
383 assert_eq!(self.current_borrow_count(py), 0); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
384 // 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
|
385 // 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
|
386 self.generation.fetch_add(1, Ordering::Relaxed); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
387 } |
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 /// Helper to keep the borrow count updated while the shared object is |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
391 /// immutably borrowed without using the `RwLock` interface. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
392 struct BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
393 py: Python<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
394 state: &'a PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
395 } |
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 impl<'a> BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
398 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
|
399 state.increase_borrow_count(py); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
400 BorrowPyShared { py, state } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
401 } |
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 impl<'a> Drop for BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
405 fn drop(&mut self) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
406 self.state.decrease_borrow_count(self.py); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
407 } |
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 |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
410 /// An immutable reference to [`PyShareable`] value, not bound to lifetime. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
411 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
412 /// 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
|
413 /// borrowed. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
414 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
415 /// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
416 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
417 /// Even though [`UnsafePyLeaked`] tries to enforce the real lifetime of the |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
418 /// 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
|
419 /// 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
|
420 /// reference outlive the actual object lifetime. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
421 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
422 /// TODO these two examples would not compile if [`UnsafePyLeaked::map()`] |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
423 /// would only accept [`Fn`] instead of [`FnOnce`]. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
424 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
425 /// ```ignore |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
426 /// let outer; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
427 /// unsafe { leaked.map(py, |o| { outer = o }) }; // Bad |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
428 /// ``` |
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 /// ```ignore |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
431 /// let outer; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
432 /// let mut leaked_iter = leaked.map(py, |o| o.iter()); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
433 /// { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
434 /// let mut iter = unsafe { leaked_iter.try_borrow_mut(py) }; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
435 /// let inner = iter.next(); // Good, in borrow scope |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
436 /// outer = inner; // Bad, &'static T may outlive |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
437 /// } |
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 pub struct UnsafePyLeaked<T: ?Sized> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
440 owner: PyObject, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
441 state: &'static PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
442 /// Generation counter of data `T` captured when UnsafePyLeaked is |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
443 /// created. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
444 generation: usize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
445 /// 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
|
446 /// state.generation == self.generation. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
447 data: T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
448 } |
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 // DO NOT implement Deref for UnsafePyLeaked<T>! Dereferencing UnsafePyLeaked |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
451 // without taking Python GIL wouldn't be safe. Also, the underling reference |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
452 // is invalid if generation != state.generation. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
453 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
454 impl<T: ?Sized> UnsafePyLeaked<T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
455 // 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
|
456 // 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
|
457 // 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
|
458 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
459 // 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
|
460 // have a function returning the inner &'static reference. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
461 // 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
|
462 // 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
|
463 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
464 /// Immutably borrows the wrapped value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
465 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
466 /// 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
|
467 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
468 /// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
469 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
470 /// 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
|
471 /// copy it out of the borrow scope. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
472 pub unsafe fn try_borrow<'a>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
473 &'a self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
474 py: Python<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
475 ) -> PyResult<PyLeakedRef<'a, T>> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
476 self.validate_generation(py)?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
477 Ok(PyLeakedRef { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
478 _borrow: BorrowPyShared::new(py, self.state), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
479 data: &self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
480 }) |
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 /// Mutably borrows the wrapped value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
484 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
485 /// 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
|
486 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
487 /// 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
|
488 /// `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
|
489 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
490 /// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
491 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
492 /// 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
|
493 /// copy it out of the borrow scope. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
494 pub unsafe fn try_borrow_mut<'a>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
495 &'a mut self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
496 py: Python<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
497 ) -> PyResult<PyLeakedRefMut<'a, T>> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
498 self.validate_generation(py)?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
499 Ok(PyLeakedRefMut { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
500 _borrow: BorrowPyShared::new(py, self.state), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
501 data: &mut self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
502 }) |
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 fn validate_generation(&self, py: Python) -> PyResult<()> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
506 if self.state.current_generation(py) == self.generation { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
507 Ok(()) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
508 } else { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
509 Err(PyRuntimeError::new_err( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
510 "Cannot access to leaked reference after mutation", |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
511 )) |
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 impl<T> UnsafePyLeaked<T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
517 /// Converts the inner value by the given function. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
518 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
519 /// 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
|
520 /// iterator of that collection. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
521 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
522 /// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
523 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
524 /// Panics if the underlying reference has been invalidated. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
525 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
526 /// This is typically called immediately after the `UnsafePyLeaked` is |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
527 /// 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
|
528 /// would occur. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
529 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
530 /// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
531 /// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
532 /// 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
|
533 /// It's typically a static reference, but is valid only while the |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
534 /// corresponding `UnsafePyLeaked` is alive. Do not copy it out of the |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
535 /// function call. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
536 /// 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
|
537 pub unsafe fn map<U>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
538 self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
539 py: Python, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
540 f: impl FnOnce(T) -> U, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
541 ) -> UnsafePyLeaked<U> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
542 // 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
|
543 // is still intact. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
544 self.validate_generation(py) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
545 .expect("map() over invalidated leaked reference"); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
546 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
547 // 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
|
548 // 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
|
549 // 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
|
550 // returned object back to Something<'static>. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
551 let new_data = f(self.data); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
552 UnsafePyLeaked { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
553 owner: self.owner, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
554 state: self.state, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
555 generation: self.generation, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
556 data: new_data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
557 } |
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 /// An immutably borrowed reference to a leaked value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
562 pub struct PyLeakedRef<'a, T: 'a + ?Sized> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
563 _borrow: BorrowPyShared<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
564 data: &'a T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
565 } |
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 impl<'a, T: ?Sized> Deref for PyLeakedRef<'a, T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
568 type Target = T; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
569 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
570 fn deref(&self) -> &T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
571 self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
572 } |
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 /// A mutably borrowed reference to a leaked value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
576 pub struct PyLeakedRefMut<'a, T: 'a + ?Sized> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
577 _borrow: BorrowPyShared<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
578 data: &'a mut T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
579 } |
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 impl<'a, T: ?Sized> Deref for PyLeakedRefMut<'a, T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
582 type Target = T; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
583 |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
584 fn deref(&self) -> &T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
585 self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
586 } |
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 impl<'a, T: ?Sized> DerefMut for PyLeakedRefMut<'a, T> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
590 fn deref_mut(&mut self) -> &mut T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
591 self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
592 } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
593 } |