Skip to content
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

document WeakRef #26745

Closed
stevengj opened this issue Apr 8, 2018 · 8 comments · Fixed by #48565
Closed

document WeakRef #26745

stevengj opened this issue Apr 8, 2018 · 8 comments · Fixed by #48565
Labels
docs This change adds or pertains to documentation

Comments

@stevengj
Copy link
Member

stevengj commented Apr 8, 2018

The WeakRef type is exported but has no docstring and no other documentation that I can find.

@stevengj stevengj added the docs This change adds or pertains to documentation label Apr 8, 2018
@stevengj
Copy link
Member Author

stevengj commented Apr 8, 2018

Something like this, maybe:

"""
    WeakRef(x)

`w = WeakRef(x)` constructs a [weak reference](https://en.wikipedia.org/wiki/Weak_reference)
to the Julia value `x`: although `w` contains a reference to `x`, it does not prevent `x` from being 
garbage collected.   `w.value` is either `x` (if `x` has not been garbage-collected yet) or `nothing`
(if `x` has been garbage-collected).
"""

@stevengj
Copy link
Member Author

stevengj commented Apr 8, 2018

This API leaves something to be desired, however. Now that we have more efficient union handling, we might revisit #5762 and replace WeakRef with a parameterized type WeakRef{T}, with the value field being a Union{T,Nothing}.

Ideally, this would be done before 1.0 — would this count as a breaking change?

@vtjnash
Copy link
Member

vtjnash commented Apr 8, 2018

Since it is explicitly tracking an allocated object, there's no performance to be gained from parameterizing it (but some predictability to be lost)

@stevengj
Copy link
Member Author

stevengj commented Apr 8, 2018

@vtjnash, could you elaborate? If I have code that operates on a w::WeakKey like

x = w.value 
if x !== nothing
    somefunction(x)
end

then currently somefunction(x) has to be dispatched dynamically. On the other hand, if we had w::WeakKey{T}, then in principle the compiler could dispatch somefunction statically.

That is, working with WeakKey{T} objects would have the same performance as working with a (heap-allocated/mutable) Union{T,Nothing} type, rather than Any.

@maleadt
Copy link
Member

maleadt commented Mar 19, 2020

Ref #35169 for an aspect of WeakRef that should probably be included in the documentation.

@ancapdev
Copy link
Contributor

ancapdev commented Sep 7, 2020

Replying here, since #35169 is closed. This behavior that objects can be accessed after finalizers have run makes WeakRef much more awkward and difficult to use. It's also contrary to the documentation of finalizer(f, x):

Register a function f(x) to be called when there are no program-accessible references to x

Since now through WeakRef we can resurrect a reference to x.

As a practical example, consider a cache of memory mapped files (byte vectors), where some caching agent opens and maps files, and keeps weak references to these around for re-use within the application. At point of looking up a cached entry, there's no way to distinguish a finalized (i.e., unmapped) from non-finalized mapped array. How could this be implemented, without touching Mmap.mmap()? One could of course maintain a hard reference in a proxy object and orchestrate finalization with some additional state tracking to detect this situation, but is that really ideal? What's the use case for accessing objects through WeakRef post-finalization?

Edit

A few reference to how Java and .Net do it.

Java

https://docs.oracle.com/javase/8/docs/api/java/lang/ref/WeakReference.html
Transitions objects to a finalizable state after weak references are cleared.

At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable

.Net

https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/weak-references
Distinguishes 'short' and 'long' weak references, that can or cannot obtain their target past finalization.

The target of a short weak reference becomes null when the object is reclaimed by garbage collection.
...
A long weak reference is retained after the object's Finalize method has been called. This allows the object to be recreated, but the state of the object remains unpredictable.

@tthsqe12
Copy link
Contributor

tthsqe12 commented Oct 1, 2021

It should be noted that it appears the undesirable behaviour of #35169 is now gone at least in version 1.6, which guarantees that WeakRef's don't reach finalized objects. It would be great to have developer confirmation here as well as some official documentation.

@tthsqe12
Copy link
Contributor

tthsqe12 commented Oct 2, 2021

Although #38180 made no mention of WeakRef (only WeakKey?), this is the pr that changed the behaviour of WeakRef.

simonbyrne added a commit that referenced this issue Feb 6, 2023
Fixes #26745. Based on suggestion by @stevengj (#26745 (comment)).
vtjnash pushed a commit that referenced this issue Feb 10, 2023
Fixes #26745. Based on suggestion by stevengj (#26745 (comment)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This change adds or pertains to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants