##// END OF EJS Templates
rust-cpython: introduce restricted variant of RefCell...
Yuya Nishihara -
r43115:8db8fa1d default
parent child Browse files
Show More
@@ -16,11 +16,12 b' use cpython::{'
16 Python,
16 Python,
17 };
17 };
18
18
19 use crate::{dirstate::extract_dirstate, ref_sharing::PySharedState};
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, self.$data_member(py).borrow_mut())
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