-
Notifications
You must be signed in to change notification settings - Fork 49
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
Add a weak type Gc pointer #148
base: master
Are you sure you want to change the base?
Conversation
Do we want to generalize weak references to ephemerons? Ephemerons can be used to implement weak maps, while plain weak references cannot. |
Hmm. It's worth considering this from a perf POV as well. I wonder if there's a way to do this without imposing additional costs on GC users that don't need Weak. And yeah, proper ephemeron support would be nice. |
One of the methods, which is mentioned in a couple places, may be to flag the box if a weak ref is present, ignore it on trace and add it to a queue, and then go through queue and run trace on the nodes flagged as weak to determine if it's target has a strong root. I had thought about that approach, but the only way I could think to do that way to update the Trace trait to contain something like:
I ended up going with the above because changing up Trace seemed little extreme at the time. Although, maybe that is the better option, especially given performance for just Gc users. |
@andersk and @Manishearth, I made a some changes to align a bit more with ephemorons as mentioned above. Is this more along the lines of what you were looking for? I opted for implementing a I should note that the changes made do differ a bit from the paper Racket cites regarding ephemerons by not adding the ephemerons found in |
I'll let @andersk have a look first but yeah this does look closer? I think. |
These still aren’t ephemerons. Ephemerons are pairs TBH I’m not sure what it would mean to evaluate the correctness of this implementation, given that we currently have known correctness bugs:
so maybe we should think about fixing those first. |
Is that first issue still occurring for you regarding resurrecting dead objects (#124)? I'm not able to replicate the behavior (the object seems to print out the value for me). |
Yes, it still reproduces on I’ve opened #149 with my reproduction in the form of a failing test case. |
I took the test from the submitted PR and added it to this commit (hope you don't mind! Can definitely remove it from the PR if you'd prefer😄). The test you provided passes on my computer for both this current branch and my local master branch Is it possible for this to be hardware related? Also, I still have to do some testing, but is this looking more along the lines of what you were thinking of? I added an |
gc/src/weak/ephemeron.rs
Outdated
pub struct Ephemeron<T: Trace + ?Sized + 'static> { | ||
key: Cell<NonNull<GcBox<T>>>, | ||
value: Cell<Option<NonNull<GcBox<T>>>>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ephemeron
should have two type parameters Ephemeron<K, V>
, not one type parameter Ephemeron<T>
. I think it should look more like
pub struct Ephemeron<K: Trace + ?Sized + 'static, V: Trace + ?Sized + 'static> {
key: Cell<NonNull<GcBox<K>>>,
value: V,
}
so that it’s up to the user whether value
is of type ()
or Option<…>
or Gc<…>
or anything else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense, but shouldn't Ephemeron
's value field be an Option, because we probably need to be able to set the value to None. I think is a change that needs to be added to Ephemeron
's Finalizer trait, so that when an ephemeron key isn't reachable and the ephemeron is finalized, we set value to None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a follow up, I did try to implement the struct as listed above, but was having a lot of difficulty getting that version of the Ephemeron
to work with Trace
and queuing process during the second phase of marking.
The more I think about it too. Would it be best to assume/restrict values coming in as K
or V
/Option<V>
as any Gc
's would ideally come in as implemented methods on Gc
to create a WeakGc
and WeakPair
?
gc/src/weak/weak_gc.rs
Outdated
pub struct WeakGc<T: Trace + ?Sized + 'static> { | ||
ptr_root: Cell<NonNull<GcBox<Ephemeron<T>>>>, | ||
marker: PhantomData<Rc<T>>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extra pointer indirection shouldn’t be necessary here. We should be able to simply use
pub struct WeakGc<T: Trace + ?Sized + 'static> {
ephemeron: Ephemeron<T, ()>,
}
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we need the GcBox
pointer that contains the Ephemeron
here. The weak_trace
that runs during the ephemeron marking phase needs to be able to enqueue the pointer...am I overthinking it?
After reading #65, I thought I'd try and implement a weak reference type
Gc
. Thought I would submit this as a draft PR for feedback to see what changes may need to be made regarding what's been completed.