@@ -170,6 +170,86 @@ impl BorrowFlags {
170170 unsafe fn get ( & self ) -> & mut HashMap < usize , isize > {
171171 ( * self . 0 . get ( ) ) . get_or_insert_with ( HashMap :: new)
172172 }
173+
174+ fn acquire < T , D > ( & self , array : & PyArray < T , D > ) -> Result < ( ) , BorrowError > {
175+ let address = base_address ( array) ;
176+
177+ // SAFETY: Access to `&PyArray<T, D>` implies holding the GIL
178+ // and we are not calling into user code which might re-enter this function.
179+ let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
180+
181+ match borrow_flags. entry ( address) {
182+ Entry :: Occupied ( entry) => {
183+ let readers = entry. into_mut ( ) ;
184+
185+ let new_readers = readers. wrapping_add ( 1 ) ;
186+
187+ if new_readers <= 0 {
188+ cold ( ) ;
189+ return Err ( BorrowError :: AlreadyBorrowed ) ;
190+ }
191+
192+ * readers = new_readers;
193+ }
194+ Entry :: Vacant ( entry) => {
195+ entry. insert ( 1 ) ;
196+ }
197+ }
198+
199+ Ok ( ( ) )
200+ }
201+
202+ fn release < T , D > ( & self , array : & PyArray < T , D > ) {
203+ let address = base_address ( array) ;
204+
205+ // SAFETY: Access to `&PyArray<T, D>` implies holding the GIL
206+ // and we are not calling into user code which might re-enter this function.
207+ let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
208+
209+ let readers = borrow_flags. get_mut ( & address) . unwrap ( ) ;
210+
211+ * readers -= 1 ;
212+
213+ if * readers == 0 {
214+ borrow_flags. remove ( & address) . unwrap ( ) ;
215+ }
216+ }
217+
218+ fn acquire_mut < T , D > ( & self , array : & PyArray < T , D > ) -> Result < ( ) , BorrowError > {
219+ let address = base_address ( array) ;
220+
221+ // SAFETY: Access to `&PyArray<T, D>` implies holding the GIL
222+ // and we are not calling into user code which might re-enter this function.
223+ let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
224+
225+ match borrow_flags. entry ( address) {
226+ Entry :: Occupied ( entry) => {
227+ let writers = entry. into_mut ( ) ;
228+
229+ if * writers != 0 {
230+ cold ( ) ;
231+ return Err ( BorrowError :: AlreadyBorrowed ) ;
232+ }
233+
234+ * writers = -1 ;
235+ }
236+ Entry :: Vacant ( entry) => {
237+ entry. insert ( -1 ) ;
238+ }
239+ }
240+
241+ Ok ( ( ) )
242+ }
243+
244+ fn release_mut < T , D > ( & self , array : & PyArray < T , D > ) {
245+ let address = base_address ( array) ;
246+
247+ // SAFETY: Access to `&PyArray<T, D>` implies holding the GIL
248+ // and we are not calling into user code which might re-enter this function.
249+ let borrow_flags = unsafe { self . get ( ) } ;
250+
251+ borrow_flags. remove ( & address) . unwrap ( ) ;
252+ }
173253}
174254
175255static BORROW_FLAGS : BorrowFlags = BorrowFlags :: new ( ) ;
@@ -224,29 +304,7 @@ where
224304 D : Dimension ,
225305{
226306 pub ( crate ) fn try_new ( array : & ' py PyArray < T , D > ) -> Result < Self , BorrowError > {
227- let address = base_address ( array) ;
228-
229- // SAFETY: Access to a `&'py PyArray<T, D>` implies holding the GIL
230- // and we are not calling into user code which might re-enter this function.
231- let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
232-
233- match borrow_flags. entry ( address) {
234- Entry :: Occupied ( entry) => {
235- let readers = entry. into_mut ( ) ;
236-
237- let new_readers = readers. wrapping_add ( 1 ) ;
238-
239- if new_readers <= 0 {
240- cold ( ) ;
241- return Err ( BorrowError :: AlreadyBorrowed ) ;
242- }
243-
244- * readers = new_readers;
245- }
246- Entry :: Vacant ( entry) => {
247- entry. insert ( 1 ) ;
248- }
249- }
307+ BORROW_FLAGS . acquire ( array) ?;
250308
251309 Ok ( Self ( array) )
252310 }
@@ -275,21 +333,19 @@ where
275333 }
276334}
277335
336+ impl < ' a , T , D > Clone for PyReadonlyArray < ' a , T , D >
337+ where
338+ T : Element ,
339+ D : Dimension ,
340+ {
341+ fn clone ( & self ) -> Self {
342+ Self :: try_new ( self . 0 ) . unwrap ( )
343+ }
344+ }
345+
278346impl < ' a , T , D > Drop for PyReadonlyArray < ' a , T , D > {
279347 fn drop ( & mut self ) {
280- let address = base_address ( self . 0 ) ;
281-
282- // SAFETY: Access to a `&'py PyArray<T, D>` implies holding the GIL
283- // and we are not calling into user code which might re-enter this function.
284- let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
285-
286- let readers = borrow_flags. get_mut ( & address) . unwrap ( ) ;
287-
288- * readers -= 1 ;
289-
290- if * readers == 0 {
291- borrow_flags. remove ( & address) . unwrap ( ) ;
292- }
348+ BORROW_FLAGS . release ( self . 0 ) ;
293349 }
294350}
295351
@@ -348,27 +404,7 @@ where
348404 return Err ( BorrowError :: NotWriteable ) ;
349405 }
350406
351- let address = base_address ( array) ;
352-
353- // SAFETY: Access to a `&'py PyArray<T, D>` implies holding the GIL
354- // and we are not calling into user code which might re-enter this function.
355- let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
356-
357- match borrow_flags. entry ( address) {
358- Entry :: Occupied ( entry) => {
359- let writers = entry. into_mut ( ) ;
360-
361- if * writers != 0 {
362- cold ( ) ;
363- return Err ( BorrowError :: AlreadyBorrowed ) ;
364- }
365-
366- * writers = -1 ;
367- }
368- Entry :: Vacant ( entry) => {
369- entry. insert ( -1 ) ;
370- }
371- }
407+ BORROW_FLAGS . acquire_mut ( array) ?;
372408
373409 Ok ( Self ( array) )
374410 }
@@ -397,15 +433,44 @@ where
397433 }
398434}
399435
400- impl < ' a , T , D > Drop for PyReadwriteArray < ' a , T , D > {
401- fn drop ( & mut self ) {
402- let address = base_address ( self . 0 ) ;
436+ impl < ' py , T > PyReadwriteArray < ' py , T , Ix1 >
437+ where
438+ T : Element ,
439+ {
440+ /// Extends or truncates the length of a one-dimensional array.
441+ ///
442+ /// # Example
443+ ///
444+ /// ```
445+ /// use numpy::PyArray;
446+ /// use pyo3::Python;
447+ ///
448+ /// Python::with_gil(|py| {
449+ /// let pyarray = PyArray::arange(py, 0, 10, 1);
450+ /// assert_eq!(pyarray.len(), 10);
451+ ///
452+ /// let pyarray = pyarray.readwrite();
453+ /// let pyarray = pyarray.resize(100).unwrap();
454+ /// assert_eq!(pyarray.len(), 100);
455+ /// });
456+ /// ```
457+ pub fn resize ( self , new_elems : usize ) -> PyResult < Self > {
458+ BORROW_FLAGS . release_mut ( self . 0 ) ;
459+
460+ // SAFETY: Ownership of `self` proves exclusive access to the interior of the array.
461+ unsafe {
462+ self . 0 . resize ( new_elems) ?;
463+ }
403464
404- // SAFETY: Access to a `&'py PyArray<T, D>` implies holding the GIL
405- // and we are not calling into user code which might re-enter this function.
406- let borrow_flags = unsafe { BORROW_FLAGS . get ( ) } ;
465+ BORROW_FLAGS . acquire_mut ( self . 0 ) ?;
407466
408- borrow_flags. remove ( & address) . unwrap ( ) ;
467+ Ok ( self )
468+ }
469+ }
470+
471+ impl < ' a , T , D > Drop for PyReadwriteArray < ' a , T , D > {
472+ fn drop ( & mut self ) {
473+ BORROW_FLAGS . release_mut ( self . 0 ) ;
409474 }
410475}
411476
0 commit comments