Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdded ability to let destructors get called #57
Conversation
schets
reviewed
Mar 1, 2016
| @@ -29,17 +29,20 @@ impl Bag { | |||
| Bag(vec![]) | |||
| } | |||
|
|
|||
| fn insert<T>(&mut self, elem: *mut T) { | |||
| fn insert<T>(&mut self, elem: *mut T, do_drop: bool) { | |||
| let size = mem::size_of::<T>(); | |||
| if size > 0 { | |||
| self.0.push(Item { | |||
This comment has been minimized.
This comment has been minimized.
schets
Mar 1, 2016
Author
Member
This should never be false for structs that implement drop, so there doesn't need to be an extra check and this will behave in a sane fashion for types that implement drop if my understanding of drop flags is correct.
This comment has been minimized.
This comment has been minimized.
|
Hey, sorry for the long delay on reviewing this -- in part because I'd been pursuing a separate branch that included some dtor support, which didn't ultimately pan out. One basic problem here is that dtors are only safe for crossbeam to run if the data contained is Of course, in many cases we want to use non- Ideally, the library would give you some static protection here, perhaps through an unsafe Finally, I'd prefer not to have a flag -- I'd rather just always run dtors when the data is being torn down, and have you use a separate mechanism for cases like the queue where you want to pull out an owned message beforehand. |
This comment has been minimized.
This comment has been minimized.
|
Sorry for the late response - I've been out of town lately
Is this true? I was of the impression that Rust didn't guarantee that destructors will ever run. Also, from the perspective of an individual thread in the system, this behaves fairly similarly to an Arc - the thread unlinks an object (drops the arc), and at some arbitrary, unspecified, possibly never point in time the object is collected (last arc is dropped).
Also, I don't think this system is all that useful if only static data can be owned by Crossbeam - wouldn't that mean all data owned by Crossbeam (and not just being shuffled around) has to exist for the entire program duration? Maybe I'm misunderstanding Rust's idea of static. |
This comment has been minimized.
This comment has been minimized.
sorear
commented
Apr 5, 2016
|
@schets Easier to answer the other way around:
Yes, you are. A type satisfies the
Given: let a = MyType1::new();
let b = MyType2::new(&a);Rust guarantees that one of the following is true:
This means that If |
This comment has been minimized.
This comment has been minimized.
|
Ahhh, I was thinking of something like C++ static.
Are these possible to satisfy in the Rust type system? Having this isn't needed to write early-stage owning datastructures, but it's needed for them to be useful. |
This comment has been minimized.
This comment has been minimized.
sorear
commented
Apr 9, 2016
Well, you're not wrong, but at another level of pointyness. What
I'm sorry, I don't quite follow here.
I suspect we may be able to get away without supporting nontrivial lifetimes for a while. Didn't |
This comment has been minimized.
This comment has been minimized.
|
Ok, so I asked people on IRC about this. There is no way to assert that a type has a trivial destructor (one that does literally nothing) statically. There is an unsafe, unstable method for this,
This could be the way to go. I can't think of a way for Of course, given that unlinking is unsafe, we can just document the need for the programmer to assert all necessary preconditions for deferred destruction to be sound besides the usual epoch ones when calling |
This comment has been minimized.
This comment has been minimized.
|
@schets: |
This comment has been minimized.
This comment has been minimized.
schets
requested a review
from
stjepang
Mar 11, 2017
stjepang
requested changes
Mar 11, 2017
|
Bounds on |
| /// Assert that the value is no longer reachable from a lock-free data | ||
| /// structure and should be collected and destroyed | ||
| /// when sufficient epochs have passed. | ||
| pub unsafe fn unlinked_drop<T: Drop>(&self, val: Shared<T>) { |
This comment has been minimized.
This comment has been minimized.
and others
added some commits
Jan 14, 2016
schets
force-pushed the
schets:destructors
branch
from
abb26cd
to
851a4f9
Mar 11, 2017
This comment has been minimized.
This comment has been minimized.
|
No, it should not be |
This comment has been minimized.
This comment has been minimized.
|
Oops, I wasn't really thinking when I added that |
sstewartgallus
reviewed
Mar 11, 2017
| @@ -31,17 +31,20 @@ impl Bag { | |||
| Bag(vec![]) | |||
| } | |||
|
|
|||
| fn insert<T>(&mut self, elem: *mut T) { | |||
| fn insert<T>(&mut self, elem: *mut T, do_drop: bool) { | |||
This comment has been minimized.
This comment has been minimized.
sstewartgallus
Mar 11, 2017
Instead of having flag arguments like this you could have separate functions. For example, insert and insert_and_drop. What do you think about that?
This comment has been minimized.
This comment has been minimized.
|
I just noticed that there is no documentation on /// Assert that the value is no longer reachable from a lock-free data
/// structure and should be collected when sufficient epochs have passed.
///
/// Bear in mind that `unlinked` does not register data for deferred destruction.
/// The occupied memory will be freed as if it were a primitive array of bytes.
fn unlinked/// Assert that the value is no longer reachable from a lock-free data
/// structure and should be destroyed when sufficient epochs have passed.
///
/// Unlike with `unlinked`, data registered for recollection using `unlinked_drop`
/// will have its destructors run. This, however, also puts additional restrictions
/// on the kinds and lifetimes of data that can be passed to this function.
fn unlinked_drop |
This comment has been minimized.
This comment has been minimized.
|
I'm going to put this on hold in light of #134, since various aspects of that proposal could change how destructors are managed |
schets commentedMar 1, 2016
This allows a program to specify that unlinked memory should be dropped when it's freed. This capability is needed for owning datastructures, like hashmaps.
One thing I'm not 100% sure on is how to handle zero-sized structs. From what I know, types that implement drop can't be zero sized due to the drop flag so this doesn't explicitly handle that case (and the test case uses a 'zero sized' dropping struct but I'm still not 100% sure.
Also, this implementation doesn't provide any ordering properties of destructors. It would be nice to have the property that all unlink_drops performed by the same thread will actually drop in the same order, but this doesn't hold when migrating garbage to the global bags. I think that using 4 global bags may fix this, I'm not sure how useful of a property this really is and whether affecting the rest of crossbeam is worth it.