author | Georges Racinet <georges.racinet@cloudcrane.io> |
Sun, 15 Dec 2024 15:36:11 +0100 | |
changeset 52612 | a945845137b1 |
parent 52611 | 4a73eb3923ac |
child 52614 | 76a0bdb0e4ca |
permissions | -rw-r--r-- |
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 |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
42 |
/// [`SharedByPyObject`] fields. |
52606
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. |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
50 |
/// The [`PyShareableRef::share_immutable()`] and |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
51 |
/// [`SharedByPyObject::map()`] 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 { |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
104 |
/// rust_iter: SharedByPyObject<IterHashSet<'static, i32>>, |
52606
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; |
52612
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
113 |
/// let iter = unsafe { rust_set.share_map(s, |o| o.iter()) }; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
114 |
/// Self { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
115 |
/// rust_iter: iter.into(), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
116 |
/// } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
117 |
/// } |
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 |
/// fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
120 |
/// slf |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
121 |
/// } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
122 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
123 |
/// 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
|
124 |
/// let py = slf.py(); |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
125 |
/// let shared = &mut slf.rust_iter; |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
126 |
/// let mut inner = unsafe { shared.try_borrow_mut(py) }?; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
127 |
/// Ok(inner.next().copied()) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
128 |
/// } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
129 |
/// } |
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 |
/// /// 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
|
132 |
/// 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
|
133 |
/// locals.py().run(statement, None, Some(locals)) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
134 |
/// } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
135 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
136 |
/// # pyo3::prepare_freethreaded_python(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
137 |
/// Python::with_gil(|py| { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
138 |
/// 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
|
139 |
/// let set = Bound::new(py, Set::new(&tuple)?)?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
140 |
/// let iter = Bound::new(py, Set::__iter__(&set))?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
141 |
/// let locals = PyDict::new(py); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
142 |
/// locals.set_item("rust_set", set).unwrap(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
143 |
/// locals.set_item("rust_iter", iter).unwrap(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
144 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
145 |
/// /// iterating on our Rust set just works |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
146 |
/// py_run( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
147 |
/// 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
|
148 |
/// &locals, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
149 |
/// )?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
150 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
151 |
/// /// 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
|
152 |
/// /// becomes invalid. Attempts to use it raise `RuntimeError`. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
153 |
/// 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
|
154 |
/// 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
|
155 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
156 |
/// let exc_repr = format!("{:?}", err.value(py)); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
157 |
/// assert_eq!( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
158 |
/// exc_repr, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
159 |
/// "RuntimeError('Cannot access to shared reference after mutation')" |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
160 |
/// ); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
161 |
/// # Ok::<(), PyErr>(()) |
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 |
/// # .expect("This example should not return an error"); |
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 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
166 |
/// 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
|
167 |
/// Python iterator. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
168 |
/// |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
169 |
/// [`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
|
170 |
/// 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
|
171 |
/// a lifetime-bound reference to the [`PyShareable`]. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
172 |
#[derive(Debug)] |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
173 |
pub struct PyShareable<T: ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
174 |
state: PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
175 |
data: RwLock<T>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
176 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
177 |
|
52612
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
178 |
impl<T: 'static> PyShareable<T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
179 |
/// 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
|
180 |
/// on the owner Python object. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
181 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
182 |
/// # Safety |
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 |
/// The `data` must be owned by the `owner`. Otherwise, calling |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
185 |
/// `share_immutable()` on the shared ref would create an invalid |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
186 |
/// reference. |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
187 |
pub unsafe fn borrow_with_owner<'py>( |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
188 |
&'py self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
189 |
owner: &'py Bound<'py, PyAny>, |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
190 |
) -> PyShareableRef<'py, T> { |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
191 |
PyShareableRef { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
192 |
owner, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
193 |
state: &self.state, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
194 |
data: &self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
195 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
196 |
} |
52612
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
197 |
|
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
198 |
/// Share for other Python objects |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
199 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
200 |
/// # Safety |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
201 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
202 |
/// The `data` must be owned by the `owner`. Otherwise, the resulting |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
203 |
/// [`SharedByPyObject`] would contain an invalid reference. |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
204 |
pub unsafe fn share<'py>( |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
205 |
&'py self, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
206 |
owner: &'py Bound<'py, PyAny>, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
207 |
) -> SharedByPyObject<&'static T> { |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
208 |
self.borrow_with_owner(owner).share_immutable() |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
209 |
} |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
210 |
|
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
211 |
/// Share for other Python objects, transforming the inner data |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
212 |
/// with a closure |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
213 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
214 |
/// # Safety |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
215 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
216 |
/// The `data` must be owned by the `owner`. Otherwise, the resulting |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
217 |
/// [`SharedByPyObject`] would contain an invalid reference. |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
218 |
pub unsafe fn share_map<'py, U>( |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
219 |
&'py self, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
220 |
owner: &'py Bound<'py, PyAny>, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
221 |
f: impl FnOnce(&'static T) -> U, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
222 |
) -> SharedByPyObject<U> { |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
223 |
self.share(owner).map(owner.py(), f) |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
224 |
} |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
225 |
|
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
226 |
/// # Safety |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
227 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
228 |
/// The `data` must be owned by the `owner`. Otherwise, the resulting |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
229 |
/// [`SharedByPyObject`] would contain an invalid reference. |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
230 |
pub unsafe fn try_share<'py>( |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
231 |
&'py self, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
232 |
owner: &'py Bound<'py, PyAny>, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
233 |
) -> Result<SharedByPyObject<&'static T>, TryShareError> { |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
234 |
self.borrow_with_owner(owner).try_share_immutable() |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
235 |
} |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
236 |
|
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
237 |
/// # Safety |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
238 |
/// |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
239 |
/// The `data` must be owned by the `owner`. Otherwise, the resulting |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
240 |
/// [`SharedByPyObject`] would contain an invalid reference. |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
241 |
pub unsafe fn try_share_map<'py, U>( |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
242 |
&'py self, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
243 |
owner: &'py Bound<'py, PyAny>, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
244 |
f: impl FnOnce(&'static T) -> U, |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
245 |
) -> Result<SharedByPyObject<U>, TryShareError> { |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
246 |
Ok(self.try_share(owner)?.map(owner.py(), f)) |
a945845137b1
rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52611
diff
changeset
|
247 |
} |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
248 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
249 |
|
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
250 |
impl<T> From<T> for PyShareable<T> { |
52608
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
251 |
fn from(value: T) -> Self { |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
252 |
Self { |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
253 |
state: PySharedState::new(), |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
254 |
data: value.into(), |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
255 |
} |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
256 |
} |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
257 |
} |
d85514a88706
rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52606
diff
changeset
|
258 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
259 |
/// Errors that can happen in `share_immutable()` |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
260 |
#[derive(Debug, PartialEq, Eq)] |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
261 |
pub enum TryShareError { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
262 |
/// 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
|
263 |
InnerLockPoisoned, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
264 |
/// 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
|
265 |
InnerLockWouldBlock, |
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 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
268 |
impl<T> From<TryLockError<T>> for TryShareError { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
269 |
fn from(e: TryLockError<T>) -> Self { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
270 |
match e { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
271 |
TryLockError::Poisoned(_) => Self::InnerLockPoisoned, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
272 |
TryLockError::WouldBlock => Self::InnerLockWouldBlock, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
273 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
274 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
275 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
276 |
|
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
277 |
/// 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
|
278 |
/// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
279 |
/// 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
|
280 |
/// 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
|
281 |
/// we make one. |
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
282 |
pub struct PyShareableRef<'py, T: 'py + ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
283 |
owner: &'py Bound<'py, PyAny>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
284 |
state: &'py PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
285 |
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
|
286 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
287 |
|
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
288 |
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
|
289 |
/// 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
|
290 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
291 |
/// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
292 |
/// |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
293 |
/// 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
|
294 |
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
|
295 |
self.try_read().expect("already mutably borrowed") |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
296 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
297 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
298 |
/// 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
|
299 |
/// 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
|
300 |
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
|
301 |
// 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
|
302 |
// - 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
|
303 |
// - 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
|
304 |
self.data.try_read() |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
305 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
306 |
|
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
307 |
/// 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
|
308 |
/// |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
309 |
/// Any existing shared references will be invalidated. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
310 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
311 |
/// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
312 |
/// |
52609
d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52608
diff
changeset
|
313 |
/// 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
|
314 |
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
|
315 |
self.try_write().expect("already borrowed") |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
316 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
317 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
318 |
/// 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
|
319 |
/// 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
|
320 |
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> { |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
321 |
// the value may be immutably borrowed through SharedByPyObject |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
322 |
if self.state.current_borrow_count(self.py()) > 0 { |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
323 |
// propagate borrow-by-shared state to data to get BorrowMutError |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
324 |
let _dummy = self.data.read(); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
325 |
let _unused = self.data.try_write()?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
326 |
unreachable!("BorrowMutError should have been returned"); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
327 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
328 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
329 |
let data_ref = self.data.try_write()?; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
330 |
self.state.increment_generation(self.py()); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
331 |
Ok(data_ref) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
332 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
333 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
334 |
/// 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
|
335 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
336 |
/// # Panics |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
337 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
338 |
/// Panics if the value is currently mutably borrowed. |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
339 |
pub fn share_immutable(&self) -> SharedByPyObject<&'static T> { |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
340 |
self.try_share_immutable() |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
341 |
.expect("already mutably borrowed") |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
342 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
343 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
344 |
/// 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
|
345 |
/// returning an error if the value is currently mutably borrowed. |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
346 |
pub fn try_share_immutable( |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
347 |
&self, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
348 |
) -> Result<SharedByPyObject<&'static T>, TryShareError> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
349 |
// 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
|
350 |
// 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
|
351 |
let data_ref = self.try_read()?; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
352 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
353 |
// 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
|
354 |
// 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
|
355 |
// the state wouldn't since it is immutable. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
356 |
let state_ptr: *const PySharedState = self.state; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
357 |
let data_ptr: *const T = &*data_ref; |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
358 |
Ok(SharedByPyObject::<&'static T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
359 |
owner: self.owner.clone().unbind(), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
360 |
state: unsafe { &*state_ptr }, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
361 |
generation: self.state.current_generation(self.py()), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
362 |
data: unsafe { &*data_ptr }, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
363 |
}) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
364 |
} |
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 |
/// Retrieve the GIL handle |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
367 |
fn py(&self) -> Python<'py> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
368 |
// 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
|
369 |
// 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
|
370 |
// of `Bound` does it for us. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
371 |
self.owner.py() |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
372 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
373 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
374 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
375 |
/// The shared state between Python and Rust |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
376 |
/// |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
377 |
/// `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
|
378 |
/// 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
|
379 |
/// as follows: |
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 |
/// - 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
|
382 |
/// [`PyShareable`] is allowed only through its `write()`. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
383 |
/// - 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
|
384 |
/// synchronized by the GIL. |
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
385 |
/// - The underlying `RefCell`, which prevents `PyShareable` value from being |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
386 |
/// directly borrowed or shared while it is mutably borrowed. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
387 |
/// - The `borrow_count`, which is the number of references borrowed from |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
388 |
/// `SharedByPyObject`. Just like `RefCell`, mutation is prohibited while |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
389 |
/// `SharedByPyObject` is borrowed. |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
390 |
/// - The `generation` counter, which increments on `write()`. |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
391 |
/// `SharedByPyObject` |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
392 |
#[derive(Debug)] |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
393 |
struct PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
394 |
// 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
|
395 |
// 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
|
396 |
// PySharedState inherently Sync. The ordering requirement doesn't |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
397 |
// 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
|
398 |
// everywhere. |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
399 |
/// The number of immutable references borrowed through shared reference. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
400 |
borrow_count: AtomicUsize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
401 |
/// The mutation counter of the underlying value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
402 |
generation: AtomicUsize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
403 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
404 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
405 |
impl PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
406 |
const fn new() -> PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
407 |
PySharedState { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
408 |
borrow_count: AtomicUsize::new(0), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
409 |
generation: AtomicUsize::new(0), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
410 |
} |
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 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
413 |
fn current_borrow_count(&self, _py: Python) -> usize { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
414 |
self.borrow_count.load(Ordering::Relaxed) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
415 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
416 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
417 |
fn increase_borrow_count(&self, _py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
418 |
// 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
|
419 |
// 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
|
420 |
self.borrow_count.fetch_add(1, Ordering::Relaxed); |
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 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
423 |
fn decrease_borrow_count(&self, _py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
424 |
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
|
425 |
assert!(prev_count > 0); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
426 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
427 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
428 |
fn current_generation(&self, _py: Python) -> usize { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
429 |
self.generation.load(Ordering::Relaxed) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
430 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
431 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
432 |
fn increment_generation(&self, py: Python) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
433 |
assert_eq!(self.current_borrow_count(py), 0); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
434 |
// 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
|
435 |
// 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
|
436 |
self.generation.fetch_add(1, Ordering::Relaxed); |
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 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
440 |
/// 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
|
441 |
/// immutably borrowed without using the `RwLock` interface. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
442 |
struct BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
443 |
py: Python<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
444 |
state: &'a PySharedState, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
445 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
446 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
447 |
impl<'a> BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
448 |
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
|
449 |
state.increase_borrow_count(py); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
450 |
BorrowPyShared { py, state } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
451 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
452 |
} |
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<'a> Drop for BorrowPyShared<'a> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
455 |
fn drop(&mut self) { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
456 |
self.state.decrease_borrow_count(self.py); |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
457 |
} |
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 |
|
52610
c25d345f5aa5
rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52609
diff
changeset
|
460 |
/// 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
|
461 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
462 |
/// 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
|
463 |
/// borrowed. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
464 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
465 |
/// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
466 |
/// |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
467 |
/// Even though [`SharedByPyObject`] tries to enforce the real lifetime of the |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
468 |
/// 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
|
469 |
/// 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
|
470 |
/// reference outlive the actual object lifetime. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
471 |
/// |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
472 |
/// TODO this first example would not compile if [`SharedByPyObject::map()`] |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
473 |
/// would only accept [`Fn`] instead of [`FnOnce`]. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
474 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
475 |
/// ```ignore |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
476 |
/// let outer; |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
477 |
/// unsafe { shared.map(py, |o| { outer = o }) }; // Bad |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
478 |
/// ``` |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
479 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
480 |
/// ```ignore |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
481 |
/// let outer; |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
482 |
/// let mut shared_iter = shared.map(py, |o| o.iter()); |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
483 |
/// { |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
484 |
/// let mut iter = unsafe { shared_iter.try_borrow_mut(py) }; |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
485 |
/// let inner = iter.next(); // Good, in borrow scope |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
486 |
/// outer = inner; // Bad, &'static T may outlive |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
487 |
/// } |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
488 |
/// ``` |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
489 |
pub struct SharedByPyObject<T: ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
490 |
owner: PyObject, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
491 |
state: &'static PySharedState, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
492 |
/// Generation counter of data `T` captured when SharedByPyObject is |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
493 |
/// created. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
494 |
generation: usize, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
495 |
/// 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
|
496 |
/// state.generation == self.generation. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
497 |
data: T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
498 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
499 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
500 |
// DO NOT implement Deref for SharedByPyObject<T>! Dereferencing |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
501 |
// SharedByPyObject without taking Python GIL wouldn't be safe. Also, the |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
502 |
// underling reference is invalid if generation != state.generation. |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
503 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
504 |
impl<T: ?Sized> SharedByPyObject<T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
505 |
// 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
|
506 |
// 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
|
507 |
// 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
|
508 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
509 |
// 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
|
510 |
// have a function returning the inner &'static reference. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
511 |
// 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
|
512 |
// 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
|
513 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
514 |
/// Immutably borrows the wrapped value. |
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 |
/// 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
|
517 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
518 |
/// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
519 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
520 |
/// 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
|
521 |
/// copy it out of the borrow scope. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
522 |
pub unsafe fn try_borrow<'a>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
523 |
&'a self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
524 |
py: Python<'a>, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
525 |
) -> PyResult<SharedByPyObjectRef<'a, T>> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
526 |
self.validate_generation(py)?; |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
527 |
Ok(SharedByPyObjectRef { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
528 |
_borrow: BorrowPyShared::new(py, self.state), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
529 |
data: &self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
530 |
}) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
531 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
532 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
533 |
/// Mutably borrows the wrapped value. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
534 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
535 |
/// 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
|
536 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
537 |
/// 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
|
538 |
/// `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
|
539 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
540 |
/// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
541 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
542 |
/// 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
|
543 |
/// copy it out of the borrow scope. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
544 |
pub unsafe fn try_borrow_mut<'a>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
545 |
&'a mut self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
546 |
py: Python<'a>, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
547 |
) -> PyResult<SharedByPyObjectRefMut<'a, T>> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
548 |
self.validate_generation(py)?; |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
549 |
Ok(SharedByPyObjectRefMut { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
550 |
_borrow: BorrowPyShared::new(py, self.state), |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
551 |
data: &mut self.data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
552 |
}) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
553 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
554 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
555 |
fn validate_generation(&self, py: Python) -> PyResult<()> { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
556 |
if self.state.current_generation(py) == self.generation { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
557 |
Ok(()) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
558 |
} else { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
559 |
Err(PyRuntimeError::new_err( |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
560 |
"Cannot access to shared reference after mutation", |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
561 |
)) |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
562 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
563 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
564 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
565 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
566 |
impl<T> SharedByPyObject<T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
567 |
/// Converts the inner value by the given function. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
568 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
569 |
/// 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
|
570 |
/// iterator of that collection. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
571 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
572 |
/// # Panics |
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 |
/// Panics if the underlying reference has been invalidated. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
575 |
/// |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
576 |
/// This is typically called immediately after the `SharedByPyObject` is |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
577 |
/// 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
|
578 |
/// would occur. |
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 |
/// # Safety |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
581 |
/// |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
582 |
/// 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
|
583 |
/// It's typically a static reference, but is valid only while the |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
584 |
/// corresponding `SharedByPyObject` is alive. Do not copy it out of the |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
585 |
/// function call. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
586 |
/// 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
|
587 |
pub unsafe fn map<U>( |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
588 |
self, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
589 |
py: Python, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
590 |
f: impl FnOnce(T) -> U, |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
591 |
) -> SharedByPyObject<U> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
592 |
// 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
|
593 |
// is still intact. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
594 |
self.validate_generation(py) |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
595 |
.expect("map() over invalidated shared reference"); |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
596 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
597 |
// 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
|
598 |
// 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
|
599 |
// 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
|
600 |
// returned object back to Something<'static>. |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
601 |
let new_data = f(self.data); |
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
602 |
SharedByPyObject { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
603 |
owner: self.owner, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
604 |
state: self.state, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
605 |
generation: self.generation, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
606 |
data: new_data, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
607 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
608 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
609 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
610 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
611 |
/// An immutably borrowed reference to a shared value. |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
612 |
pub struct SharedByPyObjectRef<'a, T: 'a + ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
613 |
_borrow: BorrowPyShared<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
614 |
data: &'a T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
615 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
616 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
617 |
impl<'a, T: ?Sized> Deref for SharedByPyObjectRef<'a, T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
618 |
type Target = T; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
619 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
620 |
fn deref(&self) -> &T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
621 |
self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
622 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
623 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
624 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
625 |
/// A mutably borrowed reference to a shared value. |
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
626 |
pub struct SharedByPyObjectRefMut<'a, T: 'a + ?Sized> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
627 |
_borrow: BorrowPyShared<'a>, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
628 |
data: &'a mut T, |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
629 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
630 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
631 |
impl<'a, T: ?Sized> Deref for SharedByPyObjectRefMut<'a, T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
632 |
type Target = T; |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
633 |
|
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
634 |
fn deref(&self) -> &T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
635 |
self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
636 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
637 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
638 |
|
52611
4a73eb3923ac
rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52610
diff
changeset
|
639 |
impl<'a, T: ?Sized> DerefMut for SharedByPyObjectRefMut<'a, T> { |
52606
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
640 |
fn deref_mut(&mut self) -> &mut T { |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
641 |
self.data |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
642 |
} |
be765f6797cc
rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
643 |
} |