annotate rust/hg-cpython/src/ref_sharing.rs @ 43961:b69d5f3a41d0

rust-index: add a struct wrapping the C index Implementing the full index logic in one go is journey larger than we would like. To achieve a smoother transition, we start with a simple Rust wrapper that delegates allwork to the current C implementation. Once we will have a fully working index object in Rust, we can easily start using more and more Rust Code with it. The object in this patch is functional and tested. However, multiple of the currently existing rust (in the `hg-cpython` crate) requires a `Graph`. Right now we build this `Graph` (as cindex::Index) using the C index passed as a PyObject. They will have to be updated to be made compatible. Differential Revision: https://phab.mercurial-scm.org/D7655
author Georges Racinet <georges.racinet@octobus.net>
date Mon, 23 Dec 2019 10:02:50 -0800
parents 8418b77132c1
children 1f9e6fbdd3e6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
43082
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
1 // ref_sharing.rs
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
2 //
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
4 //
43082
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
6 // of this software and associated documentation files (the "Software"), to
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
7 // deal in the Software without restriction, including without limitation the
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
9 // sell copies of the Software, and to permit persons to whom the Software is
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
10 // furnished to do so, subject to the following conditions:
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
11 //
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
12 // The above copyright notice and this permission notice shall be included in
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
13 // all copies or substantial portions of the Software.
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
14 //
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
fdfe5cfb3723 rust-cpython: change license of ref_sharing.rs to MIT
Yuya Nishihara <yuya@tcha.org>
parents: 42939
diff changeset
21 // IN THE SOFTWARE.
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
22
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
23 //! Macros for use in the `hg-cpython` bridge library.
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
24
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
25 use crate::exceptions::AlreadyBorrowed;
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
26 use cpython::{exc, PyClone, PyErr, PyObject, PyResult, Python};
43428
6c0e47874217 rust-cpython: drop manual management of mutably_borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43427
diff changeset
27 use std::cell::{Ref, RefCell, RefMut};
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
28 use std::ops::{Deref, DerefMut};
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
29 use std::sync::atomic::{AtomicUsize, Ordering};
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
30
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
31 /// Manages the shared state between Python and Rust
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
32 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
33 /// `PySharedState` is owned by `PySharedRefCell`, and is shared across its
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
34 /// derived references. The consistency of these references are guaranteed
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
35 /// as follows:
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
36 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
37 /// - The immutability of `py_class!` object fields. Any mutation of
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
38 /// `PySharedRefCell` is allowed only through its `borrow_mut()`.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
39 /// - The `py: Python<'_>` token, which makes sure that any data access is
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
40 /// synchronized by the GIL.
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
41 /// - The underlying `RefCell`, which prevents `PySharedRefCell` data from
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
42 /// being directly borrowed or leaked while it is mutably borrowed.
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
43 /// - The `borrow_count`, which is the number of references borrowed from
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
44 /// `PyLeaked`. Just like `RefCell`, mutation is prohibited while `PyLeaked`
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
45 /// is borrowed.
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
46 /// - The `generation` counter, which increments on `borrow_mut()`. `PyLeaked`
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
47 /// reference is valid only if the `current_generation()` equals to the
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
48 /// `generation` at the time of `leak_immutable()`.
43173
070a38737334 rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents: 43082
diff changeset
49 #[derive(Debug, Default)]
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
50 struct PySharedState {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
51 // The counter variable could be Cell<usize> since any operation on
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
52 // PySharedState is synchronized by the GIL, but being "atomic" makes
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
53 // PySharedState inherently Sync. The ordering requirement doesn't
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
54 // matter thanks to the GIL.
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
55 borrow_count: AtomicUsize,
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
56 generation: AtomicUsize,
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
57 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
58
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
59 impl PySharedState {
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
60 fn borrow_mut<'a, T>(
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
61 &'a self,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
62 py: Python<'a>,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
63 pyrefmut: RefMut<'a, T>,
43429
75b4eb98ad97 rust-cpython: remove useless PyRefMut wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 43428
diff changeset
64 ) -> PyResult<RefMut<'a, T>> {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
65 match self.current_borrow_count(py) {
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
66 0 => {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
67 // Note that this wraps around to the same value if mutably
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
68 // borrowed more than usize::MAX times, which wouldn't happen
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
69 // in practice.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
70 self.generation.fetch_add(1, Ordering::Relaxed);
43429
75b4eb98ad97 rust-cpython: remove useless PyRefMut wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 43428
diff changeset
71 Ok(pyrefmut)
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
72 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
73 _ => Err(AlreadyBorrowed::new(
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
74 py,
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
75 "Cannot borrow mutably while immutably borrowed",
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
76 )),
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
77 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
78 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
79
43176
aaec70a5f9a8 rust-cpython: store leaked reference to PySharedState in $leaked struct
Yuya Nishihara <yuya@tcha.org>
parents: 43175
diff changeset
80 /// Return a reference to the wrapped data and its state with an
aaec70a5f9a8 rust-cpython: store leaked reference to PySharedState in $leaked struct
Yuya Nishihara <yuya@tcha.org>
parents: 43175
diff changeset
81 /// artificial static lifetime.
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
82 /// We need to be protected by the GIL for thread-safety.
42851
64e28b891796 rust-cpython: mark unsafe functions as such
Yuya Nishihara <yuya@tcha.org>
parents: 42850
diff changeset
83 ///
64e28b891796 rust-cpython: mark unsafe functions as such
Yuya Nishihara <yuya@tcha.org>
parents: 42850
diff changeset
84 /// # Safety
64e28b891796 rust-cpython: mark unsafe functions as such
Yuya Nishihara <yuya@tcha.org>
parents: 42850
diff changeset
85 ///
64e28b891796 rust-cpython: mark unsafe functions as such
Yuya Nishihara <yuya@tcha.org>
parents: 42850
diff changeset
86 /// This is highly unsafe since the lifetime of the given data can be
64e28b891796 rust-cpython: mark unsafe functions as such
Yuya Nishihara <yuya@tcha.org>
parents: 42850
diff changeset
87 /// extended. Do not call this function directly.
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
88 unsafe fn leak_immutable<T>(
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
89 &self,
43428
6c0e47874217 rust-cpython: drop manual management of mutably_borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43427
diff changeset
90 _py: Python,
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
91 data: Ref<T>,
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
92 ) -> (&'static T, &'static PySharedState) {
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
93 let ptr: *const T = &*data;
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
94 let state_ptr: *const PySharedState = self;
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
95 (&*ptr, &*state_ptr)
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
96 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
97
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
98 fn current_borrow_count(&self, _py: Python) -> usize {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
99 self.borrow_count.load(Ordering::Relaxed)
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
100 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
101
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
102 fn increase_borrow_count(&self, _py: Python) {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
103 // Note that this wraps around if there are more than usize::MAX
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
104 // borrowed references, which shouldn't happen due to memory limit.
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
105 self.borrow_count.fetch_add(1, Ordering::Relaxed);
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
106 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
107
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
108 fn decrease_borrow_count(&self, _py: Python) {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
109 let prev_count = self.borrow_count.fetch_sub(1, Ordering::Relaxed);
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
110 assert!(prev_count > 0);
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
111 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
112
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
113 fn current_generation(&self, _py: Python) -> usize {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
114 self.generation.load(Ordering::Relaxed)
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
115 }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
116 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
117
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
118 /// Helper to keep the borrow count updated while the shared object is
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
119 /// immutably borrowed without using the `RefCell` interface.
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
120 struct BorrowPyShared<'a> {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
121 py: Python<'a>,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
122 py_shared_state: &'a PySharedState,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
123 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
124
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
125 impl<'a> BorrowPyShared<'a> {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
126 fn new(
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
127 py: Python<'a>,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
128 py_shared_state: &'a PySharedState,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
129 ) -> BorrowPyShared<'a> {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
130 py_shared_state.increase_borrow_count(py);
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
131 BorrowPyShared {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
132 py,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
133 py_shared_state,
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
134 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
135 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
136 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
137
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
138 impl Drop for BorrowPyShared<'_> {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
139 fn drop(&mut self) {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
140 self.py_shared_state.decrease_borrow_count(self.py);
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
141 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
142 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
143
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
144 /// `RefCell` wrapper to be safely used in conjunction with `PySharedState`.
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
145 ///
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
146 /// This object can be stored in a `py_class!` object as a data field. Any
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
147 /// operation is allowed through the `PySharedRef` interface.
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
148 #[derive(Debug)]
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
149 pub struct PySharedRefCell<T> {
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
150 inner: RefCell<T>,
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
151 py_shared_state: PySharedState,
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
152 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
153
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
154 impl<T> PySharedRefCell<T> {
43173
070a38737334 rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents: 43082
diff changeset
155 pub fn new(value: T) -> PySharedRefCell<T> {
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
156 Self {
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
157 inner: RefCell::new(value),
43173
070a38737334 rust-cpython: move py_shared_state to PySharedRefCell object
Yuya Nishihara <yuya@tcha.org>
parents: 43082
diff changeset
158 py_shared_state: PySharedState::default(),
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
159 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
160 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
161
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
162 fn borrow<'a>(&'a self, _py: Python<'a>) -> Ref<'a, T> {
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
163 // py_shared_state isn't involved since
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
164 // - inner.borrow() would fail if self is mutably borrowed,
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
165 // - and inner.borrow_mut() would fail while self is borrowed.
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
166 self.inner.borrow()
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
167 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
168
43174
1c675c5fe5fe rust-cpython: move borrow_mut() to PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43173
diff changeset
169 // TODO: maybe this should be named as try_borrow_mut(), and use
1c675c5fe5fe rust-cpython: move borrow_mut() to PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43173
diff changeset
170 // inner.try_borrow_mut(). The current implementation panics if
1c675c5fe5fe rust-cpython: move borrow_mut() to PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43173
diff changeset
171 // self.inner has been borrowed, but returns error if py_shared_state
1c675c5fe5fe rust-cpython: move borrow_mut() to PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43173
diff changeset
172 // refuses to borrow.
43429
75b4eb98ad97 rust-cpython: remove useless PyRefMut wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 43428
diff changeset
173 fn borrow_mut<'a>(&'a self, py: Python<'a>) -> PyResult<RefMut<'a, T>> {
43174
1c675c5fe5fe rust-cpython: move borrow_mut() to PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43173
diff changeset
174 self.py_shared_state.borrow_mut(py, self.inner.borrow_mut())
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
175 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
176 }
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
177
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
178 /// Sharable data member of type `T` borrowed from the `PyObject`.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
179 pub struct PySharedRef<'a, T> {
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
180 py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
181 owner: &'a PyObject,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
182 data: &'a PySharedRefCell<T>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
183 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
184
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
185 impl<'a, T> PySharedRef<'a, T> {
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
186 /// # Safety
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
187 ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
188 /// The `data` must be owned by the `owner`. Otherwise, the leak count
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
189 /// would get wrong.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
190 pub unsafe fn new(
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
191 py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
192 owner: &'a PyObject,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
193 data: &'a PySharedRefCell<T>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
194 ) -> Self {
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
195 Self { py, owner, data }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
196 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
197
43272
00222775d59b rust-refsharing: add missing lifetime parameter in ref_sharing
Rapha?l Gom?s <rgomes@octobus.net>
parents: 43180
diff changeset
198 pub fn borrow(&self) -> Ref<'a, T> {
43286
f8c114f20d2d rust-cpython: require GIL to borrow immutable reference from PySharedRefCell
Yuya Nishihara <yuya@tcha.org>
parents: 43285
diff changeset
199 self.data.borrow(self.py)
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
200 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
201
43429
75b4eb98ad97 rust-cpython: remove useless PyRefMut wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 43428
diff changeset
202 pub fn borrow_mut(&self) -> PyResult<RefMut<'a, T>> {
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
203 self.data.borrow_mut(self.py)
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
204 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
205
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
206 /// Returns a leaked reference.
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
207 ///
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
208 /// # Panics
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
209 ///
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
210 /// Panics if this is mutably borrowed.
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
211 pub fn leak_immutable(&self) -> PyLeaked<&'static T> {
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
212 let state = &self.data.py_shared_state;
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
213 // make sure self.data isn't mutably borrowed; otherwise the
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
214 // generation number can't be trusted.
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
215 let data_ref = self.borrow();
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
216 unsafe {
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
217 let (static_ref, static_state_ref) =
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
218 state.leak_immutable(self.py, data_ref);
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
219 PyLeaked::new(self.py, self.owner, static_ref, static_state_ref)
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
220 }
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
221 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
222 }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
223
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
224 /// Allows a `py_class!` generated struct to share references to one of its
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
225 /// data members with Python.
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
226 ///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
227 /// # Parameters
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
228 ///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
229 /// * `$name` is the same identifier used in for `py_class!` macro call.
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
230 /// * `$inner_struct` is the identifier of the underlying Rust struct
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
231 /// * `$data_member` is the identifier of the data member of `$inner_struct`
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
232 /// that will be shared.
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
233 /// * `$shared_accessor` is the function name to be generated, which allows
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
234 /// safe access to the data member.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
235 ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
236 /// # Safety
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
237 ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
238 /// `$data_member` must persist while the `$name` object is alive. In other
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
239 /// words, it must be an accessor to a data field of the Python object.
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
240 ///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
241 /// # Example
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
242 ///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
243 /// ```
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
244 /// struct MyStruct {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
245 /// inner: Vec<u32>;
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
246 /// }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
247 ///
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
248 /// py_class!(pub class MyType |py| {
42849
8db8fa1de2ef rust-cpython: introduce restricted variant of RefCell
Yuya Nishihara <yuya@tcha.org>
parents: 42839
diff changeset
249 /// data inner: PySharedRefCell<MyStruct>;
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
250 /// });
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
251 ///
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
252 /// py_shared_ref!(MyType, MyStruct, inner, inner_shared);
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
253 /// ```
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
254 macro_rules! py_shared_ref {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
255 (
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
256 $name: ident,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
257 $inner_struct: ident,
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
258 $data_member: ident,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
259 $shared_accessor: ident
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
260 ) => {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
261 impl $name {
43178
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
262 /// Returns a safe reference to the shared `$data_member`.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
263 ///
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
264 /// This function guarantees that `PySharedRef` is created with
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
265 /// the valid `self` and `self.$data_member(py)` pair.
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
266 fn $shared_accessor<'a>(
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
267 &'a self,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
268 py: Python<'a>,
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
269 ) -> $crate::ref_sharing::PySharedRef<'a, $inner_struct> {
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
270 use cpython::PythonObject;
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
271 use $crate::ref_sharing::PySharedRef;
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
272 let owner = self.as_object();
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
273 let data = self.$data_member(py);
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
274 unsafe { PySharedRef::new(py, owner, data) }
1b2200bd06b6 rust-cpython: add safe wrapper representing shared data borrowed from PyObject
Yuya Nishihara <yuya@tcha.org>
parents: 43177
diff changeset
275 }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
276 }
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
277 };
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
278 }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
279
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
280 /// Manage immutable references to `PyObject` leaked into Python iterators.
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
281 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
282 /// This reference will be invalidated once the original value is mutably
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
283 /// borrowed.
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
284 pub struct PyLeaked<T> {
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
285 inner: PyObject,
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
286 data: Option<T>,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
287 py_shared_state: &'static PySharedState,
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
288 /// Generation counter of data `T` captured when PyLeaked is created.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
289 generation: usize,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
290 }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
291
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
292 // DO NOT implement Deref for PyLeaked<T>! Dereferencing PyLeaked
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
293 // without taking Python GIL wouldn't be safe. Also, the underling reference
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
294 // is invalid if generation != py_shared_state.generation.
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
295
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
296 impl<T> PyLeaked<T> {
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
297 /// # Safety
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
298 ///
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
299 /// The `py_shared_state` must be owned by the `inner` Python object.
43288
434d7a3e92e3 rust-cpython: make inner functions and structs of ref_sharing private
Yuya Nishihara <yuya@tcha.org>
parents: 43287
diff changeset
300 fn new(
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
301 py: Python,
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
302 inner: &PyObject,
43284
ce6dd1cee4c8 rust-cpython: put leaked reference in PyLeakedRef
Yuya Nishihara <yuya@tcha.org>
parents: 43272
diff changeset
303 data: T,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
304 py_shared_state: &'static PySharedState,
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
305 ) -> Self {
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
306 Self {
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
307 inner: inner.clone_ref(py),
43284
ce6dd1cee4c8 rust-cpython: put leaked reference in PyLeakedRef
Yuya Nishihara <yuya@tcha.org>
parents: 43272
diff changeset
308 data: Some(data),
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
309 py_shared_state,
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
310 generation: py_shared_state.current_generation(py),
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
311 }
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
312 }
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
313
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
314 /// Immutably borrows the wrapped value.
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
315 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
316 /// Borrowing fails if the underlying reference has been invalidated.
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
317 pub fn try_borrow<'a>(
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
318 &'a self,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
319 py: Python<'a>,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
320 ) -> PyResult<PyLeakedRef<'a, T>> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
321 self.validate_generation(py)?;
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
322 Ok(PyLeakedRef {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
323 _borrow: BorrowPyShared::new(py, self.py_shared_state),
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
324 data: self.data.as_ref().unwrap(),
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
325 })
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
326 }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
327
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
328 /// Mutably borrows the wrapped value.
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
329 ///
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
330 /// Borrowing fails if the underlying reference has been invalidated.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
331 ///
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
332 /// Typically `T` is an iterator. If `T` is an immutable reference,
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
333 /// `get_mut()` is useless since the inner value can't be mutated.
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
334 pub fn try_borrow_mut<'a>(
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
335 &'a mut self,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
336 py: Python<'a>,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
337 ) -> PyResult<PyLeakedRefMut<'a, T>> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
338 self.validate_generation(py)?;
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
339 Ok(PyLeakedRefMut {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
340 _borrow: BorrowPyShared::new(py, self.py_shared_state),
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
341 data: self.data.as_mut().unwrap(),
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
342 })
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
343 }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
344
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
345 /// Converts the inner value by the given function.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
346 ///
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
347 /// Typically `T` is a static reference to a container, and `U` is an
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
348 /// iterator of that container.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
349 ///
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
350 /// # Panics
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
351 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
352 /// Panics if the underlying reference has been invalidated.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
353 ///
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
354 /// This is typically called immediately after the `PyLeaked` is obtained.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
355 /// In which case, the reference must be valid and no panic would occur.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
356 ///
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
357 /// # Safety
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
358 ///
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
359 /// The lifetime of the object passed in to the function `f` is cheated.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
360 /// It's typically a static reference, but is valid only while the
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
361 /// corresponding `PyLeaked` is alive. Do not copy it out of the
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
362 /// function call.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
363 pub unsafe fn map<U>(
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
364 mut self,
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
365 py: Python,
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
366 f: impl FnOnce(T) -> U,
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
367 ) -> PyLeaked<U> {
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
368 // Needs to test the generation value to make sure self.data reference
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
369 // is still intact.
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
370 self.validate_generation(py)
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
371 .expect("map() over invalidated leaked reference");
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
372
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
373 // f() could make the self.data outlive. That's why map() is unsafe.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
374 // In order to make this function safe, maybe we'll need a way to
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
375 // temporarily restrict the lifetime of self.data and translate the
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
376 // returned object back to Something<'static>.
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
377 let new_data = f(self.data.take().unwrap());
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
378 PyLeaked {
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
379 inner: self.inner.clone_ref(py),
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
380 data: Some(new_data),
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
381 py_shared_state: self.py_shared_state,
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
382 generation: self.generation,
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
383 }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
384 }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
385
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
386 fn validate_generation(&self, py: Python) -> PyResult<()> {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
387 if self.py_shared_state.current_generation(py) == self.generation {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
388 Ok(())
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
389 } else {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
390 Err(PyErr::new::<exc::RuntimeError, _>(
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
391 py,
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
392 "Cannot access to leaked reference after mutation",
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
393 ))
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
394 }
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
395 }
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
396 }
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
397
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
398 /// Immutably borrowed reference to a leaked value.
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
399 pub struct PyLeakedRef<'a, T> {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
400 _borrow: BorrowPyShared<'a>,
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
401 data: &'a T,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
402 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
403
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
404 impl<T> Deref for PyLeakedRef<'_, T> {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
405 type Target = T;
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
406
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
407 fn deref(&self) -> &T {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
408 self.data
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
409 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
410 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
411
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
412 /// Mutably borrowed reference to a leaked value.
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
413 pub struct PyLeakedRefMut<'a, T> {
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
414 _borrow: BorrowPyShared<'a>,
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
415 data: &'a mut T,
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
416 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
417
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
418 impl<T> Deref for PyLeakedRefMut<'_, T> {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
419 type Target = T;
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
420
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
421 fn deref(&self) -> &T {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
422 self.data
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
423 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
424 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
425
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
426 impl<T> DerefMut for PyLeakedRefMut<'_, T> {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
427 fn deref_mut(&mut self) -> &mut T {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
428 self.data
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
429 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
430 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
431
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
432 /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator.
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
433 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
434 /// TODO: this is a bit awkward to use, and a better (more complicated)
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
435 /// procedural macro would simplify the interface a lot.
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
436 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
437 /// # Parameters
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
438 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
439 /// * `$name` is the identifier to give to the resulting Rust struct.
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
440 /// * `$leaked` corresponds to `$leaked` in the matching `py_shared_ref!` call.
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
441 /// * `$iterator_type` is the type of the Rust iterator.
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
442 /// * `$success_func` is a function for processing the Rust `(key, value)`
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
443 /// tuple on iteration success, turning it into something Python understands.
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
444 /// * `$success_func` is the return type of `$success_func`
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
445 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
446 /// # Example
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
447 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
448 /// ```
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
449 /// struct MyStruct {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
450 /// inner: HashMap<Vec<u8>, Vec<u8>>;
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
451 /// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
452 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
453 /// py_class!(pub class MyType |py| {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
454 /// data inner: PySharedRefCell<MyStruct>;
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
455 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
456 /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> {
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
457 /// let leaked_ref = self.inner_shared(py).leak_immutable();
42891
5ccc08d02280 rust-cpython: leverage py_shared_iterator::from_inner() where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 42890
diff changeset
458 /// MyTypeItemsIterator::from_inner(
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
459 /// py,
43285
ffc1fbd7d1f5 rust-cpython: make PyLeakedRef operations relatively safe
Yuya Nishihara <yuya@tcha.org>
parents: 43284
diff changeset
460 /// unsafe { leaked_ref.map(py, |o| o.iter()) },
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
461 /// )
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
462 /// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
463 /// });
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
464 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
465 /// impl MyType {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
466 /// fn translate_key_value(
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
467 /// py: Python,
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
468 /// res: (&Vec<u8>, &Vec<u8>),
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
469 /// ) -> PyResult<Option<(PyBytes, PyBytes)>> {
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
470 /// let (f, entry) = res;
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
471 /// Ok(Some((
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
472 /// PyBytes::new(py, f),
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
473 /// PyBytes::new(py, entry),
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
474 /// )))
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
475 /// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
476 /// }
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
477 ///
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
478 /// py_shared_ref!(MyType, MyStruct, inner, MyTypeLeakedRef);
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
479 ///
42889
ea91a126c803 rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42888
diff changeset
480 /// py_shared_iterator!(
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
481 /// MyTypeItemsIterator,
43422
b9f791090211 rust-cpython: rename PyLeakedRef to PyLeaked
Yuya Nishihara <yuya@tcha.org>
parents: 43289
diff changeset
482 /// PyLeaked<HashMap<'static, Vec<u8>, Vec<u8>>>,
42888
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
483 /// MyType::translate_key_value,
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
484 /// Option<(PyBytes, PyBytes)>
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
485 /// );
67853749961b rust-cpython: replace dyn Iterator<..> of mapping with concrete type
Yuya Nishihara <yuya@tcha.org>
parents: 42887
diff changeset
486 /// ```
42889
ea91a126c803 rust-cpython: rename py_shared_iterator_impl to py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42888
diff changeset
487 macro_rules! py_shared_iterator {
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
488 (
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
489 $name: ident,
43177
5cb8867c9e2b rust-cpython: move $leaked struct out of macro
Yuya Nishihara <yuya@tcha.org>
parents: 43176
diff changeset
490 $leaked: ty,
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
491 $success_func: expr,
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
492 $success_type: ty
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
493 ) => {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
494 py_class!(pub class $name |py| {
43426
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
495 data inner: RefCell<$leaked>;
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
496
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
497 def __next__(&self) -> PyResult<$success_type> {
43426
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
498 let mut leaked = self.inner(py).borrow_mut();
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
499 let mut iter = leaked.try_borrow_mut(py)?;
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
500 match iter.next() {
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
501 None => Ok(None),
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
502 Some(res) => $success_func(py, res),
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
503 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
504 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
505
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
506 def __iter__(&self) -> PyResult<Self> {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
507 Ok(self.clone_ref(py))
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
508 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
509 });
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
510
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
511 impl $name {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
512 pub fn from_inner(
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
513 py: Python,
42890
74d67c645278 rust-cpython: remove Option<_> from interface of py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 42889
diff changeset
514 leaked: $leaked,
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
515 ) -> PyResult<Self> {
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
516 Self::create_instance(
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
517 py,
43426
6f9f15a476a4 rust-cpython: remove useless Option<$leaked> from py_shared_iterator
Yuya Nishihara <yuya@tcha.org>
parents: 43425
diff changeset
518 RefCell::new(leaked),
42752
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
519 )
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
520 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
521 }
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
522 };
30320c7bf79f rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
523 }
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
524
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
525 #[cfg(test)]
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
526 #[cfg(any(feature = "python27-bin", feature = "python3-bin"))]
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
527 mod test {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
528 use super::*;
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
529 use cpython::{GILGuard, Python};
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
530
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
531 py_class!(class Owner |py| {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
532 data string: PySharedRefCell<String>;
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
533 });
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
534 py_shared_ref!(Owner, String, string, string_shared);
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
535
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
536 fn prepare_env() -> (GILGuard, Owner) {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
537 let gil = Python::acquire_gil();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
538 let py = gil.python();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
539 let owner =
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
540 Owner::create_instance(py, PySharedRefCell::new("new".to_owned()))
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
541 .unwrap();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
542 (gil, owner)
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
543 }
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
544
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
545 #[test]
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
546 fn test_leaked_borrow() {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
547 let (gil, owner) = prepare_env();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
548 let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
549 let leaked = owner.string_shared(py).leak_immutable();
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
550 let leaked_ref = leaked.try_borrow(py).unwrap();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
551 assert_eq!(*leaked_ref, "new");
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
552 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
553
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
554 #[test]
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
555 fn test_leaked_borrow_mut() {
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
556 let (gil, owner) = prepare_env();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
557 let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
558 let leaked = owner.string_shared(py).leak_immutable();
43423
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
559 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
560 let mut leaked_ref = leaked_iter.try_borrow_mut(py).unwrap();
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
561 assert_eq!(leaked_ref.next(), Some('n'));
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
562 assert_eq!(leaked_ref.next(), Some('e'));
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
563 assert_eq!(leaked_ref.next(), Some('w'));
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
564 assert_eq!(leaked_ref.next(), None);
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
565 }
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
566
945d4dba5e78 rust-cpython: add stub wrapper that'll prevent leaked data from being mutated
Yuya Nishihara <yuya@tcha.org>
parents: 43422
diff changeset
567 #[test]
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
568 fn test_leaked_borrow_after_mut() {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
569 let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
570 let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
571 let leaked = owner.string_shared(py).leak_immutable();
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
572 owner.string_shared(py).borrow_mut().unwrap().clear();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
573 assert!(leaked.try_borrow(py).is_err());
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
574 }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
575
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
576 #[test]
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
577 fn test_leaked_borrow_mut_after_mut() {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
578 let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
579 let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
580 let leaked = owner.string_shared(py).leak_immutable();
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
581 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
582 owner.string_shared(py).borrow_mut().unwrap().clear();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
583 assert!(leaked_iter.try_borrow_mut(py).is_err());
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
584 }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
585
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
586 #[test]
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
587 #[should_panic(expected = "map() over invalidated leaked reference")]
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
588 fn test_leaked_map_after_mut() {
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
589 let (gil, owner) = prepare_env();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
590 let py = gil.python();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
591 let leaked = owner.string_shared(py).leak_immutable();
43424
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
592 owner.string_shared(py).borrow_mut().unwrap().clear();
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
593 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
594 }
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
595
0836efe4967b rust-cpython: add generation counter to leaked reference
Yuya Nishihara <yuya@tcha.org>
parents: 43423
diff changeset
596 #[test]
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
597 fn test_borrow_mut_while_leaked_ref() {
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
598 let (gil, owner) = prepare_env();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
599 let py = gil.python();
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
600 assert!(owner.string_shared(py).borrow_mut().is_ok());
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
601 let leaked = owner.string_shared(py).leak_immutable();
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
602 {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
603 let _leaked_ref = leaked.try_borrow(py).unwrap();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
604 assert!(owner.string_shared(py).borrow_mut().is_err());
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
605 {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
606 let _leaked_ref2 = leaked.try_borrow(py).unwrap();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
607 assert!(owner.string_shared(py).borrow_mut().is_err());
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
608 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
609 assert!(owner.string_shared(py).borrow_mut().is_err());
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
610 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
611 assert!(owner.string_shared(py).borrow_mut().is_ok());
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
612 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
613
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
614 #[test]
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
615 fn test_borrow_mut_while_leaked_ref_mut() {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
616 let (gil, owner) = prepare_env();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
617 let py = gil.python();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
618 assert!(owner.string_shared(py).borrow_mut().is_ok());
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
619 let leaked = owner.string_shared(py).leak_immutable();
43425
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
620 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
621 {
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
622 let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap();
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
623 assert!(owner.string_shared(py).borrow_mut().is_err());
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
624 }
ed50f2c31a4c rust-cpython: allow mutation unless leaked reference is borrowed
Yuya Nishihara <yuya@tcha.org>
parents: 43424
diff changeset
625 assert!(owner.string_shared(py).borrow_mut().is_ok());
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
626 }
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
627
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
628 #[test]
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
629 #[should_panic(expected = "mutably borrowed")]
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
630 fn test_leak_while_borrow_mut() {
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
631 let (gil, owner) = prepare_env();
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
632 let py = gil.python();
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
633 let _mut_ref = owner.string_shared(py).borrow_mut();
43430
8418b77132c1 rust-cpython: remove useless PyResult<> from leak_immutable()
Yuya Nishihara <yuya@tcha.org>
parents: 43429
diff changeset
634 owner.string_shared(py).leak_immutable();
43427
b7ab3a0a9e57 rust-cpython: leverage RefCell::borrow() to guarantee there's no mutable ref
Yuya Nishihara <yuya@tcha.org>
parents: 43426
diff changeset
635 }
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43288
diff changeset
636 }