Source file src/weak/pointer.go
1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package weak 6 7 import ( 8 "internal/abi" 9 "runtime" 10 "unsafe" 11 ) 12 13 // Pointer is a weak pointer to a value of type T. 14 // 15 // Just like regular pointers, Pointer may reference any part of an 16 // object, such as a 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. 20 // 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 compare equal if and only if the pointers from which they 27 // were created compare equal. 28 // This property is maintained even after the object referenced by the pointer 29 // used to create a weak reference is reclaimed. 30 // If multiple weak pointers are made to different offsets within the same object 31 // (for example, pointers to different fields of the same struct), those pointers 32 // will not compare equal. 33 // In other words, weak pointers map to objects and offsets within those 34 // objects, not plain addresses. 35 // If a weak pointer is created from an object that becomes unreachable, but is 36 // then resurrected due to a finalizer, that weak pointer will not compare equal 37 // with weak pointers created after the resurrection. 38 // 39 // Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value] 40 // always returns nil. The zero value of a Pointer behaves as if it were created 41 // by passing nil to [Make] and compares equal with such pointers. 42 // 43 // [Pointer.Value] is not guaranteed to eventually return nil. 44 // [Pointer.Value] may return nil as soon as the object becomes 45 // unreachable. 46 // Values stored in global variables, or that can be found by tracing 47 // pointers from a global variable, are reachable. A function argument or 48 // receiver may become unreachable at the last point where the function 49 // mentions it. To ensure [Pointer.Value] does not return nil, 50 // pass a pointer to the object to the [runtime.KeepAlive] function after 51 // the last point where the object must remain reachable. 52 // 53 // Note that because [Pointer.Value] is not guaranteed to eventually return 54 // nil, even after an object is no longer referenced, the runtime is allowed to 55 // perform a space-saving optimization that batches objects together in a single 56 // allocation slot. The weak pointer for an unreferenced object in such an 57 // allocation may never become nil if it always exists in the same batch as a 58 // referenced object. Typically, this batching only happens for tiny 59 // (on the order of 16 bytes or less) and pointer-free objects. 60 type Pointer[T any] struct { 61 // Mention T in the type definition to prevent conversions 62 // between Pointer types, like we do for sync/atomic.Pointer. 63 _ [0]*T 64 u unsafe.Pointer 65 } 66 67 // Make creates a weak pointer from a pointer to some value of type T. 68 func Make[T any](ptr *T) Pointer[T] { 69 // Explicitly force ptr to escape to the heap. 70 ptr = abi.Escape(ptr) 71 72 var u unsafe.Pointer 73 if ptr != nil { 74 u = runtime_registerWeakPointer(unsafe.Pointer(ptr)) 75 } 76 runtime.KeepAlive(ptr) 77 return Pointer[T]{u: u} 78 } 79 80 // Value returns the original pointer used to create the weak pointer. 81 // It returns nil if the value pointed to by the original pointer was reclaimed by 82 // the garbage collector. 83 // If a weak pointer points to an object with a finalizer, then Value will 84 // return nil as soon as the object's finalizer is queued for execution. 85 func (p Pointer[T]) Value() *T { 86 if p.u == nil { 87 return nil 88 } 89 return (*T)(runtime_makeStrongFromWeak(p.u)) 90 } 91 92 // Implemented in runtime. 93 94 //go:linkname runtime_registerWeakPointer 95 func runtime_registerWeakPointer(unsafe.Pointer) unsafe.Pointer 96 97 //go:linkname runtime_makeStrongFromWeak 98 func runtime_makeStrongFromWeak(unsafe.Pointer) unsafe.Pointer 99