Show More
@@ -16,11 +16,12 b' use cpython::{' | |||||
16 | Python, |
|
16 | Python, | |
17 | }; |
|
17 | }; | |
18 |
|
18 | |||
19 |
use crate:: |
|
19 | use crate::dirstate::extract_dirstate; | |
|
20 | use crate::ref_sharing::{PySharedRefCell, PySharedState}; | |||
20 | use hg::{DirsMultiset, DirstateMapError, DirstateParseError, EntryState}; |
|
21 | use hg::{DirsMultiset, DirstateMapError, DirstateParseError, EntryState}; | |
21 |
|
22 | |||
22 | py_class!(pub class Dirs |py| { |
|
23 | py_class!(pub class Dirs |py| { | |
23 | data inner: RefCell<DirsMultiset>; |
|
24 | data inner: PySharedRefCell<DirsMultiset>; | |
24 | data py_shared_state: PySharedState; |
|
25 | data py_shared_state: PySharedState; | |
25 |
|
26 | |||
26 | // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes |
|
27 | // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes | |
@@ -53,7 +54,7 b' py_class!(pub class Dirs |py| {' | |||||
53 |
|
54 | |||
54 | Self::create_instance( |
|
55 | Self::create_instance( | |
55 | py, |
|
56 | py, | |
56 | RefCell::new(inner), |
|
57 | PySharedRefCell::new(inner), | |
57 | PySharedState::default() |
|
58 | PySharedState::default() | |
58 | ) |
|
59 | ) | |
59 | } |
|
60 | } | |
@@ -104,7 +105,11 b' py_shared_ref!(Dirs, DirsMultiset, inner' | |||||
104 |
|
105 | |||
105 | impl Dirs { |
|
106 | impl Dirs { | |
106 | pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> { |
|
107 | pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> { | |
107 | Self::create_instance(py, RefCell::new(d), PySharedState::default()) |
|
108 | Self::create_instance( | |
|
109 | py, | |||
|
110 | PySharedRefCell::new(d), | |||
|
111 | PySharedState::default(), | |||
|
112 | ) | |||
108 | } |
|
113 | } | |
109 |
|
114 | |||
110 | fn translate_key(py: Python, res: &Vec<u8>) -> PyResult<Option<PyBytes>> { |
|
115 | fn translate_key(py: Python, res: &Vec<u8>) -> PyResult<Option<PyBytes>> { |
@@ -21,7 +21,7 b' use libc::c_char;' | |||||
21 | use crate::{ |
|
21 | use crate::{ | |
22 | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, |
|
22 | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, | |
23 | dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs}, |
|
23 | dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs}, | |
24 | ref_sharing::PySharedState, |
|
24 | ref_sharing::{PySharedRefCell, PySharedState}, | |
25 | }; |
|
25 | }; | |
26 | use hg::{ |
|
26 | use hg::{ | |
27 | DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, |
|
27 | DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, | |
@@ -41,14 +41,14 b' use hg::{' | |||||
41 | // All attributes also have to have a separate refcount data attribute for |
|
41 | // All attributes also have to have a separate refcount data attribute for | |
42 | // leaks, with all methods that go along for reference sharing. |
|
42 | // leaks, with all methods that go along for reference sharing. | |
43 | py_class!(pub class DirstateMap |py| { |
|
43 | py_class!(pub class DirstateMap |py| { | |
44 | data inner: RefCell<RustDirstateMap>; |
|
44 | data inner: PySharedRefCell<RustDirstateMap>; | |
45 | data py_shared_state: PySharedState; |
|
45 | data py_shared_state: PySharedState; | |
46 |
|
46 | |||
47 | def __new__(_cls, _root: PyObject) -> PyResult<Self> { |
|
47 | def __new__(_cls, _root: PyObject) -> PyResult<Self> { | |
48 | let inner = RustDirstateMap::default(); |
|
48 | let inner = RustDirstateMap::default(); | |
49 | Self::create_instance( |
|
49 | Self::create_instance( | |
50 | py, |
|
50 | py, | |
51 | RefCell::new(inner), |
|
51 | PySharedRefCell::new(inner), | |
52 | PySharedState::default() |
|
52 | PySharedState::default() | |
53 | ) |
|
53 | ) | |
54 | } |
|
54 | } |
@@ -9,7 +9,7 b'' | |||||
9 |
|
9 | |||
10 | use crate::exceptions::AlreadyBorrowed; |
|
10 | use crate::exceptions::AlreadyBorrowed; | |
11 | use cpython::{PyResult, Python}; |
|
11 | use cpython::{PyResult, Python}; | |
12 | use std::cell::{Cell, RefCell, RefMut}; |
|
12 | use std::cell::{Cell, Ref, RefCell, RefMut}; | |
13 |
|
13 | |||
14 | /// Manages the shared state between Python and Rust |
|
14 | /// Manages the shared state between Python and Rust | |
15 | #[derive(Default)] |
|
15 | #[derive(Default)] | |
@@ -61,7 +61,7 b' impl PySharedState {' | |||||
61 | pub fn leak_immutable<T>( |
|
61 | pub fn leak_immutable<T>( | |
62 | &self, |
|
62 | &self, | |
63 | py: Python, |
|
63 | py: Python, | |
64 | data: &RefCell<T>, |
|
64 | data: &PySharedRefCell<T>, | |
65 | ) -> PyResult<&'static T> { |
|
65 | ) -> PyResult<&'static T> { | |
66 | if self.mutably_borrowed.get() { |
|
66 | if self.mutably_borrowed.get() { | |
67 | return Err(AlreadyBorrowed::new( |
|
67 | return Err(AlreadyBorrowed::new( | |
@@ -84,6 +84,38 b' impl PySharedState {' | |||||
84 | } |
|
84 | } | |
85 | } |
|
85 | } | |
86 |
|
86 | |||
|
87 | /// `RefCell` wrapper to be safely used in conjunction with `PySharedState`. | |||
|
88 | /// | |||
|
89 | /// Only immutable operation is allowed through this interface. | |||
|
90 | #[derive(Debug)] | |||
|
91 | pub struct PySharedRefCell<T> { | |||
|
92 | inner: RefCell<T>, | |||
|
93 | } | |||
|
94 | ||||
|
95 | impl<T> PySharedRefCell<T> { | |||
|
96 | pub const fn new(value: T) -> PySharedRefCell<T> { | |||
|
97 | Self { | |||
|
98 | inner: RefCell::new(value), | |||
|
99 | } | |||
|
100 | } | |||
|
101 | ||||
|
102 | pub fn borrow(&self) -> Ref<T> { | |||
|
103 | // py_shared_state isn't involved since | |||
|
104 | // - inner.borrow() would fail if self is mutably borrowed, | |||
|
105 | // - and inner.borrow_mut() would fail while self is borrowed. | |||
|
106 | self.inner.borrow() | |||
|
107 | } | |||
|
108 | ||||
|
109 | pub fn as_ptr(&self) -> *mut T { | |||
|
110 | self.inner.as_ptr() | |||
|
111 | } | |||
|
112 | ||||
|
113 | pub unsafe fn borrow_mut(&self) -> RefMut<T> { | |||
|
114 | // must be borrowed by self.py_shared_state(py).borrow_mut(). | |||
|
115 | self.inner.borrow_mut() | |||
|
116 | } | |||
|
117 | } | |||
|
118 | ||||
87 | /// Holds a mutable reference to data shared between Python and Rust. |
|
119 | /// Holds a mutable reference to data shared between Python and Rust. | |
88 | pub struct PyRefMut<'a, T> { |
|
120 | pub struct PyRefMut<'a, T> { | |
89 | inner: RefMut<'a, T>, |
|
121 | inner: RefMut<'a, T>, | |
@@ -158,7 +190,7 b" impl<'a, T> Drop for PyRefMut<'a, T> {" | |||||
158 | /// } |
|
190 | /// } | |
159 | /// |
|
191 | /// | |
160 | /// py_class!(pub class MyType |py| { |
|
192 | /// py_class!(pub class MyType |py| { | |
161 | /// data inner: RefCell<MyStruct>; |
|
193 | /// data inner: PySharedRefCell<MyStruct>; | |
162 | /// data py_shared_state: PySharedState; |
|
194 | /// data py_shared_state: PySharedState; | |
163 | /// }); |
|
195 | /// }); | |
164 | /// |
|
196 | /// | |
@@ -177,16 +209,21 b' macro_rules! py_shared_ref {' | |||||
177 | py: Python<'a>, |
|
209 | py: Python<'a>, | |
178 | ) -> PyResult<crate::ref_sharing::PyRefMut<'a, $inner_struct>> |
|
210 | ) -> PyResult<crate::ref_sharing::PyRefMut<'a, $inner_struct>> | |
179 | { |
|
211 | { | |
|
212 | // assert $data_member type | |||
|
213 | use crate::ref_sharing::PySharedRefCell; | |||
|
214 | let data: &PySharedRefCell<_> = self.$data_member(py); | |||
180 | self.py_shared_state(py) |
|
215 | self.py_shared_state(py) | |
181 |
.borrow_mut(py, |
|
216 | .borrow_mut(py, unsafe { data.borrow_mut() }) | |
182 | } |
|
217 | } | |
183 |
|
218 | |||
184 | fn leak_immutable<'a>( |
|
219 | fn leak_immutable<'a>( | |
185 | &'a self, |
|
220 | &'a self, | |
186 | py: Python<'a>, |
|
221 | py: Python<'a>, | |
187 | ) -> PyResult<&'static $inner_struct> { |
|
222 | ) -> PyResult<&'static $inner_struct> { | |
188 | self.py_shared_state(py) |
|
223 | // assert $data_member type | |
189 | .leak_immutable(py, self.$data_member(py)) |
|
224 | use crate::ref_sharing::PySharedRefCell; | |
|
225 | let data: &PySharedRefCell<_> = self.$data_member(py); | |||
|
226 | self.py_shared_state(py).leak_immutable(py, data) | |||
190 | } |
|
227 | } | |
191 | } |
|
228 | } | |
192 |
|
229 | |||
@@ -295,7 +332,7 b' macro_rules! py_shared_iterator_impl {' | |||||
295 | /// } |
|
332 | /// } | |
296 | /// |
|
333 | /// | |
297 | /// py_class!(pub class MyType |py| { |
|
334 | /// py_class!(pub class MyType |py| { | |
298 | /// data inner: RefCell<MyStruct>; |
|
335 | /// data inner: PySharedRefCell<MyStruct>; | |
299 | /// data py_shared_state: PySharedState; |
|
336 | /// data py_shared_state: PySharedState; | |
300 | /// |
|
337 | /// | |
301 | /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { |
|
338 | /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { |
General Comments 0
You need to be logged in to leave comments.
Login now