// license that can be found in the LICENSE file.
/*
-Package weak provides weak pointers with the goal of memory efficiency.
-The primary use-cases for weak pointers are for implementing caches,
-canonicalization maps (like the unique package), and for tying together
-the lifetimes of separate values (for example, through a map with weak
-keys).
-
-# Advice
-
-This package is intended to target niche use-cases like the unique
-package, and the structures inside are not intended to be general
-replacements for regular Go pointers, maps, etc.
-Misuse of the structures in this package may generate unexpected and
-hard-to-reproduce bugs.
-Using the facilities in this package to try and resolve out-of-memory
-issues requires careful consideration, and even so, will likely be the
-wrong answer if the solution does not fall into one of the listed
-use-cases above.
-
-The structures in this package are intended to be an implementation
-detail of the package they are used by (again, see the unique package).
-If you're writing a package intended to be used by others, as a rule of
-thumb, avoid exposing the behavior of any weak structures in your package's
-API.
-Doing so will almost certainly make your package more difficult to use
-correctly.
+Package weak provides ways to safely reference memory weakly,
+that is, without preventing its reclamation.
*/
package weak
// Pointer is a weak pointer to a value of type T.
//
-// Two Pointer values compare equal if the pointers
-// that they were created from compare equal. This property is retained even
-// after the object referenced by the pointer used to create a weak reference
-// is reclaimed.
+// Just like regular pointers, Pointer may reference any part of an
+// object, such as the field of a struct or an element of an array.
+// Objects that are only pointed to by weak pointers are not considered
+// reachable and once the object becomes unreachable [Pointer.Value]
+// may return nil.
//
+// The primary use-cases for weak pointers are for implementing caches,
+// canonicalization maps (like the unique package), and for tying together
+// the lifetimes of separate values (for example, through a map with weak
+// keys).
+//
+// Two Pointer values always compare equal if the pointers that they were
+// created from compare equal. This property is retained even after the
+// object referenced by the pointer used to create a weak reference is
+// reclaimed.
// If multiple weak pointers are made to different offsets within same object
// (for example, pointers to different fields of the same struct), those pointers
// will not compare equal.
// then resurrected due to a finalizer, that weak pointer will not compare equal
// with weak pointers created after resurrection.
//
-// Calling Make with a nil pointer returns a weak pointer whose Value method
+// Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value]
// always returns nil. The zero value of a Pointer behaves as if it was created
-// by passing nil to Make and compares equal with such pointers.
+// by passing nil to [Make] and compares equal with such pointers.
+//
+// [Pointer.Value] is not guaranteed to eventually return nil.
+// [Pointer.Value] may return nil as soon as the object becomes
+// unreachable.
+// Values stored in global variables, or that can be found by tracing
+// pointers from a global variable, are reachable. A function argument or
+// receiver may become unreachable at the last point where the function
+// mentions it. To ensure [Pointer.Value] does not return nil,
+// pass a pointer to the object to the [runtime.KeepAlive] function after
+// the last point where the object must remain reachable.
+//
+// Note that because [Pointer.Value] is not guaranteed to eventually return
+// nil, even after an object is no longer referenced, the runtime is allowed to
+// perform a space-saving optimization that batches objects together in a single
+// allocation slot. The weak pointer for an unreferenced object in such an
+// allocation may never be called if it always exists in the same batch as a
+// referenced object. Typically, this batching only happens for tiny
+// (on the order of 16 bytes or less) and pointer-free objects.
type Pointer[T any] struct {
u unsafe.Pointer
}
-// Make creates a weak pointer from a strong pointer to some value of type T.
+// Make creates a weak pointer from a pointer to some value of type T.
func Make[T any](ptr *T) Pointer[T] {
// Explicitly force ptr to escape to the heap.
ptr = abi.Escape(ptr)