Skip to content

Commit 07398d2

Browse files
mknyszekgopherbot
authored andcommitted
weak: align weak.Pointer documentation with runtime.AddCleanup
In hindsight, I think the "advice" I wrote is a bit heavy-handed and better suited for something like the GC guide. Listing the use-cases seems good, and all the possible things that go wrong seems to do the trick in terms of deterrence, like it does with finalizers. Also, include some points I missed, like the tiny allocator warning and the fact that weak pointers are not guaranteed to ever return nil. Also, a lot of this actually shouldn't have been in the package docs. Many of the warnings only apply to weak pointers, but not other data structures that may live in this package in the future, like weak-keyed maps. Change-Id: Id245661540ffd93de4b727cd272284491d085c1e Reviewed-on: https://go-review.googlesource.com/c/go/+/634376 Reviewed-by: Carlos Amedee <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Michael Knyszek <[email protected]>
1 parent e3e1d73 commit 07398d2

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

src/weak/doc.go

+2-25
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,7 @@
33
// license that can be found in the LICENSE file.
44

55
/*
6-
Package weak provides weak pointers with the goal of memory efficiency.
7-
The primary use-cases for weak pointers are for implementing caches,
8-
canonicalization maps (like the unique package), and for tying together
9-
the lifetimes of separate values (for example, through a map with weak
10-
keys).
11-
12-
# Advice
13-
14-
This package is intended to target niche use-cases like the unique
15-
package, and the structures inside are not intended to be general
16-
replacements for regular Go pointers, maps, etc.
17-
Misuse of the structures in this package may generate unexpected and
18-
hard-to-reproduce bugs.
19-
Using the facilities in this package to try and resolve out-of-memory
20-
issues requires careful consideration, and even so, will likely be the
21-
wrong answer if the solution does not fall into one of the listed
22-
use-cases above.
23-
24-
The structures in this package are intended to be an implementation
25-
detail of the package they are used by (again, see the unique package).
26-
If you're writing a package intended to be used by others, as a rule of
27-
thumb, avoid exposing the behavior of any weak structures in your package's
28-
API.
29-
Doing so will almost certainly make your package more difficult to use
30-
correctly.
6+
Package weak provides ways to safely reference memory weakly,
7+
that is, without preventing its reclamation.
318
*/
329
package weak

src/weak/pointer.go

+35-7
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,54 @@ import (
1212

1313
// Pointer is a weak pointer to a value of type T.
1414
//
15-
// Two Pointer values compare equal if the pointers
16-
// that they were created from compare equal. This property is retained even
17-
// after the object referenced by the pointer used to create a weak reference
18-
// is reclaimed.
15+
// Just like regular pointers, Pointer may reference any part of an
16+
// object, such as the field of a struct or an element of an array.
17+
// Objects that are only pointed to by weak pointers are not considered
18+
// reachable and once the object becomes unreachable [Pointer.Value]
19+
// may return nil.
1920
//
21+
// The primary use-cases for weak pointers are for implementing caches,
22+
// canonicalization maps (like the unique package), and for tying together
23+
// the lifetimes of separate values (for example, through a map with weak
24+
// keys).
25+
//
26+
// Two Pointer values always compare equal if the pointers that they were
27+
// created from compare equal. This property is retained even after the
28+
// object referenced by the pointer used to create a weak reference is
29+
// reclaimed.
2030
// If multiple weak pointers are made to different offsets within same object
2131
// (for example, pointers to different fields of the same struct), those pointers
2232
// will not compare equal.
2333
// If a weak pointer is created from an object that becomes unreachable, but is
2434
// then resurrected due to a finalizer, that weak pointer will not compare equal
2535
// with weak pointers created after resurrection.
2636
//
27-
// Calling Make with a nil pointer returns a weak pointer whose Value method
37+
// Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value]
2838
// always returns nil. The zero value of a Pointer behaves as if it was created
29-
// by passing nil to Make and compares equal with such pointers.
39+
// by passing nil to [Make] and compares equal with such pointers.
40+
//
41+
// [Pointer.Value] is not guaranteed to eventually return nil.
42+
// [Pointer.Value] may return nil as soon as the object becomes
43+
// unreachable.
44+
// Values stored in global variables, or that can be found by tracing
45+
// pointers from a global variable, are reachable. A function argument or
46+
// receiver may become unreachable at the last point where the function
47+
// mentions it. To ensure [Pointer.Value] does not return nil,
48+
// pass a pointer to the object to the [runtime.KeepAlive] function after
49+
// the last point where the object must remain reachable.
50+
//
51+
// Note that because [Pointer.Value] is not guaranteed to eventually return
52+
// nil, even after an object is no longer referenced, the runtime is allowed to
53+
// perform a space-saving optimization that batches objects together in a single
54+
// allocation slot. The weak pointer for an unreferenced object in such an
55+
// allocation may never be called if it always exists in the same batch as a
56+
// referenced object. Typically, this batching only happens for tiny
57+
// (on the order of 16 bytes or less) and pointer-free objects.
3058
type Pointer[T any] struct {
3159
u unsafe.Pointer
3260
}
3361

34-
// Make creates a weak pointer from a strong pointer to some value of type T.
62+
// Make creates a weak pointer from a pointer to some value of type T.
3563
func Make[T any](ptr *T) Pointer[T] {
3664
// Explicitly force ptr to escape to the heap.
3765
ptr = abi.Escape(ptr)

0 commit comments

Comments
 (0)