Skip to content

Make PyList to ThreadSafe #1871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 17, 2020
Merged

Make PyList to ThreadSafe #1871

merged 4 commits into from
Apr 17, 2020

Conversation

palaviv
Copy link
Contributor

@palaviv palaviv commented Apr 15, 2020

No description provided.

let mut elements = Vec::<u8>::with_capacity(self.get_len());
for elem in self.elements.borrow().iter() {
let mut elements = Vec::<u8>::with_capacity(self.borrow_elements().len());
for elem in self.borrow_elements().clone().iter() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this cloning of Vec or lock?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Vec. RwLock does not implement Clone

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems additional clone is added to a few places. But this is using the iterator of the vector instead of the vector itself. Is there no way to avoid this kind of clone?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, if there is python code running inside the loop body, then it could theoretically lock the pylist again and cause a panic or deadlock. Although that doesn't seem necessary for this one, @palaviv, none of the code inside the loop calls into the interpreter. Is there another reason you cloned the vec here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the clone here. I tried to clone only where python code is called.

@@ -1222,6 +1222,10 @@ pub trait PyValue: fmt::Debug + Sized + 'static {

// Temporary trait to follow the progress of threading conversion
pub trait ThreadSafe: Send + Sync {}
// Temporary definitions to help with converting object that contain PyObjectRef to ThreadSafe.
// Should be removed before threading is allowed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention here how this is technically unsound, and that PyObjects shouldn't actually be passed to or accessed by other threads?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope the new message is better. This should be a very temporary thing.

Comment on lines 780 to 782
let mut elements = PyList::_replace(self.borrow_elements_mut(), vec![]);
do_sort(vm, &mut elements, options.key, options.reverse)?;
let temp_elements = self.elements.replace(elements);
let temp_elements = PyList::_replace(self.borrow_elements_mut(), elements);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you borrow mutably here, you can just use std::mem::take() or std::mem::replace(). Something like:

let mut elements = self.borrow_elements_mut();
let mut temp_elements = std::mem::take(&mut elements);
do_sort(vm, &mut temp_elements, options.key, options.reverse)?;
std::mem::swap(&mut temp_elements, &mut elements);

}

#[pymethod]
fn count(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
let mut count: usize = 0;
for element in self.elements.borrow().iter() {
for element in self.borrow_elements().clone().iter() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be really nice if we could somehow detect if something tries to lock while we already have one and then give it a clone, but I think any solution to that would violate rust's aliasing rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The big question is how expensive is the clone. I hope that this is very quick because of the Arc.

@palaviv palaviv merged commit 1ecd94b into RustPython:master Apr 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants