rust/pyo3-sharedref/src/lib.rs
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--
rust-pyo3-sharedref: share/map methods on PyShareable The pattern to borrow (with owner) for the sole purpose of calling `share_immutable`, and then `map()` is pretty common, being exactly what is needed in the constructors of derived Python objects. we therefore introduce new helpers doing exactly that. We keep the intermediate `share()` and `try_share()` that are used in integration tests, but is is possible that consumers of the API never need it. A nice feature of the new `share_map()` helper is that it collapses all the unsafety in constructors of derived object to one call. It makes sense, since the reason for unsafety is the same all along the call stack: the `owner` object, that cannot be guessed from `PyShareable` itself, must be the right one. It is remarkable that it is only at this point that the compiler insists that `T` should be `'static`, which is actually very reasonable, as it encompasses owned data. We could have set it since the beginning, but the added value is low, as PyO3 would not let us use some `PyShareable<&'a T>` as a Python object data field (with `'a` not outliving `'static` of course)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
}