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 // 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. 19 // 20 // If multiple weak pointers are made to different offsets within same object 21 // (for example, pointers to different fields of the same struct), those pointers 22 // will not compare equal. 23 // If a weak pointer is created from an object that becomes unreachable, but is 24 // then resurrected due to a finalizer, that weak pointer will not compare equal 25 // with weak pointers created after resurrection. 26 // 27 // Calling Make with a nil pointer returns a weak pointer whose Value method 28 // 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. 30 type Pointer[T any] struct { 31 u unsafe.Pointer 32 } 33 34 // Make creates a weak pointer from a strong pointer to some value of type T. 35 func Make[T any](ptr *T) Pointer[T] { 36 // Explicitly force ptr to escape to the heap. 37 ptr = abi.Escape(ptr) 38 39 var u unsafe.Pointer 40 if ptr != nil { 41 u = runtime_registerWeakPointer(unsafe.Pointer(ptr)) 42 } 43 runtime.KeepAlive(ptr) 44 return Pointer[T]{u} 45 } 46 47 // Value returns the original pointer used to create the weak pointer. 48 // It returns nil if the value pointed to by the original pointer was reclaimed by 49 // the garbage collector. 50 // If a weak pointer points to an object with a finalizer, then Value will 51 // return nil as soon as the object's finalizer is queued for execution. 52 func (p Pointer[T]) Value() *T { 53 return (*T)(runtime_makeStrongFromWeak(p.u)) 54 } 55 56 // Implemented in runtime. 57 58 //go:linkname runtime_registerWeakPointer 59 func runtime_registerWeakPointer(unsafe.Pointer) unsafe.Pointer 60 61 //go:linkname runtime_makeStrongFromWeak 62 func runtime_makeStrongFromWeak(unsafe.Pointer) unsafe.Pointer 63