diff --git a/common/src/lock/cell_lock.rs b/common/src/lock/cell_lock.rs index df55da774..d5cc0146e 100644 --- a/common/src/lock/cell_lock.rs +++ b/common/src/lock/cell_lock.rs @@ -93,7 +93,7 @@ unsafe impl RawRwLock for RawCellRwLock { #[inline] fn lock_exclusive(&self) { if !self.try_lock_exclusive() { - deadlock("exclusively", "RwLock") + deadlock("exclusively ", "RwLock") } self.state.set(WRITER_BIT) } @@ -126,7 +126,7 @@ unsafe impl RawRwLockDowngrade for RawCellRwLock { unsafe impl RawRwLockUpgrade for RawCellRwLock { #[inline] fn lock_upgradable(&self) { - if self.try_lock_upgradable() { + if !self.try_lock_upgradable() { deadlock("upgradably+sharedly ", "RwLock") } } @@ -176,7 +176,7 @@ unsafe impl RawRwLockRecursive for RawCellRwLock { #[inline] fn lock_shared_recursive(&self) { if !self.try_lock_shared_recursive() { - deadlock("recursively+sharedly", "RwLock") + deadlock("recursively+sharedly ", "RwLock") } } diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index e8f99a51b..597b01d06 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -14,9 +14,7 @@ use crate::bytesinner::{ }; use crate::byteslike::PyBytesLike; use crate::common::borrow::{BorrowedValue, BorrowedValueMut}; -use crate::common::lock::{ - PyRwLock, PyRwLockReadGuard, PyRwLockUpgradableReadGuard, PyRwLockWriteGuard, -}; +use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::function::{OptionalArg, OptionalOption}; use crate::pyobject::{ BorrowValue, Either, IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext, @@ -45,7 +43,6 @@ use std::mem::size_of; pub struct PyByteArray { inner: PyRwLock, exports: AtomicCell, - buffer_options: PyRwLock>>, } pub type PyByteArrayRef = PyRef; @@ -63,7 +60,6 @@ impl PyByteArray { PyByteArray { inner: PyRwLock::new(inner), exports: AtomicCell::new(0), - buffer_options: PyRwLock::new(None), } } @@ -667,40 +663,42 @@ impl Comparable for PyByteArray { impl BufferProtocol for PyByteArray { fn get_buffer(zelf: &PyRef, _vm: &VirtualMachine) -> PyResult> { zelf.exports.fetch_add(1); - Ok(Box::new(zelf.clone())) + let buf = ByteArrayBuffer { + bytearray: zelf.clone(), + options: BufferOptions { + readonly: false, + len: zelf.len(), + ..Default::default() + }, + }; + Ok(Box::new(buf)) } } -impl Buffer for PyByteArrayRef { +#[derive(Debug)] +struct ByteArrayBuffer { + bytearray: PyByteArrayRef, + options: BufferOptions, +} + +impl Buffer for ByteArrayBuffer { fn obj_bytes(&self) -> BorrowedValue<[u8]> { - PyRwLockReadGuard::map(self.borrow_value(), |x| x.elements.as_slice()).into() + PyRwLockReadGuard::map(self.bytearray.borrow_value(), |x| x.elements.as_slice()).into() } fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> { - PyRwLockWriteGuard::map(self.borrow_value_mut(), |x| x.elements.as_mut_slice()).into() + PyRwLockWriteGuard::map(self.bytearray.borrow_value_mut(), |x| { + x.elements.as_mut_slice() + }) + .into() } fn release(&self) { - let mut w = self.buffer_options.write(); - if self.exports.fetch_sub(1) == 1 { - *w = None; - } + self.bytearray.exports.fetch_sub(1); } fn get_options(&self) -> BorrowedValue { - let guard = self.buffer_options.upgradable_read(); - let guard = if guard.is_none() { - let mut w = PyRwLockUpgradableReadGuard::upgrade(guard); - *w = Some(Box::new(BufferOptions { - readonly: false, - len: self.len(), - ..Default::default() - })); - PyRwLockWriteGuard::downgrade(w) - } else { - PyRwLockUpgradableReadGuard::downgrade(guard) - }; - PyRwLockReadGuard::map(guard, |x| x.as_ref().unwrap().as_ref()).into() + (&self.options).into() } } diff --git a/vm/src/builtins/memory.rs b/vm/src/builtins/memory.rs index bd2d3319d..2a85f38d6 100644 --- a/vm/src/builtins/memory.rs +++ b/vm/src/builtins/memory.rs @@ -99,16 +99,14 @@ pub trait Buffer: Debug + PyThreadingConstraint { fn release(&self); fn as_contiguous(&self) -> Option> { - let options = self.get_options(); - if !options.contiguous { + if !self.get_options().contiguous { return None; } Some(self.obj_bytes()) } fn as_contiguous_mut(&self) -> Option> { - let options = self.get_options(); - if !options.contiguous { + if !self.get_options().contiguous { return None; } Some(self.obj_bytes_mut()) @@ -513,16 +511,6 @@ impl PyMemoryView { vm: &VirtualMachine, ) -> PyResult<()> { let items = try_buffer_from_object(vm, &items)?; - let options = items.get_options(); - let len = options.len; - let itemsize = options.itemsize; - - if itemsize != zelf.options.itemsize { - return Err(vm.new_type_error(format!( - "memoryview: invalid type for format '{}'", - zelf.options.format - ))); - } let diff_err = || { Err(vm.new_value_error( @@ -530,8 +518,22 @@ impl PyMemoryView { )) }; - if options.format != zelf.options.format { - return diff_err(); + let (len, itemsize); + { + let options = items.get_options(); + len = options.len; + itemsize = options.itemsize; + + if itemsize != zelf.options.itemsize { + return Err(vm.new_type_error(format!( + "memoryview: invalid type for format '{}'", + zelf.options.format + ))); + } + + if options.format != zelf.options.format { + return diff_err(); + } } let (range, step, is_negative_step) = convert_slice(&slice, zelf.options.len, vm)?; @@ -807,8 +809,7 @@ impl Buffer for PyMemoryViewRef { } fn as_contiguous(&self) -> Option> { - let options = self.get_options(); - if !options.contiguous { + if !self.options.contiguous { return None; } Some(BorrowedValue::map(self.obj_bytes(), |x| { @@ -817,8 +818,7 @@ impl Buffer for PyMemoryViewRef { } fn as_contiguous_mut(&self) -> Option> { - let options = self.get_options(); - if !options.contiguous { + if !self.options.contiguous { return None; } Some(BorrowedValueMut::map(self.obj_bytes_mut(), |x| { diff --git a/vm/src/byteslike.rs b/vm/src/byteslike.rs index 0d48ebf3c..010894366 100644 --- a/vm/src/byteslike.rs +++ b/vm/src/byteslike.rs @@ -97,11 +97,13 @@ pub fn try_rw_bytes_like( impl PyRwBytesLike { pub fn new(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { let buffer = try_buffer_from_object(vm, &obj)?; - if !buffer.get_options().contiguous { + let options = buffer.get_options(); + if !options.contiguous { Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned())) - } else if buffer.get_options().readonly { + } else if options.readonly { Err(vm.new_type_error("buffer is not a read-write bytes-like object".to_owned())) } else { + drop(options); Ok(Self(buffer)) } }