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/* 6The weak package is a package for managing weak pointers. 7 8Weak pointers are pointers that explicitly do not keep a value live and 9must be queried for a regular Go pointer. 10The result of such a query may be observed as nil at any point after a 11weakly-pointed-to object becomes eligible for reclamation by the garbage 12collector. 13More specifically, weak pointers become nil as soon as the garbage collector 14identifies that the object is unreachable, before it is made reachable 15again by a finalizer. 16In terms of the C# language, these semantics are roughly equivalent to the 17the semantics of "short" weak references. 18In terms of the Java language, these semantics are roughly equivalent to the 19semantics of the WeakReference type. 20 21Using go:linkname to access this package and the functions it references 22is explicitly forbidden by the toolchain because the semantics of this 23package have not gone through the proposal process. By exposing this 24functionality, we risk locking in the existing semantics due to Hyrum's Law. 25 26If you believe you have a good use-case for weak references not already 27covered by the standard library, file a proposal issue at 28https://github.com/golang/go/issues instead of relying on this package. 29*/ 30package weak 31 32import ( 33 "internal/abi" 34 "runtime" 35 "unsafe" 36) 37 38// Pointer is a weak pointer to a value of type T. 39// 40// This value is comparable is guaranteed to compare equal if the pointers 41// that they were created from compare equal. This property is retained even 42// after the object referenced by the pointer used to create a weak reference 43// is reclaimed. 44// 45// If multiple weak pointers are made to different offsets within same object 46// (for example, pointers to different fields of the same struct), those pointers 47// will not compare equal. 48// If a weak pointer is created from an object that becomes reachable again due 49// to a finalizer, that weak pointer will not compare equal with weak pointers 50// created before it became unreachable. 51type Pointer[T any] struct { 52 u unsafe.Pointer 53} 54 55// Make creates a weak pointer from a strong pointer to some value of type T. 56func Make[T any](ptr *T) Pointer[T] { 57 // Explicitly force ptr to escape to the heap. 58 ptr = abi.Escape(ptr) 59 60 var u unsafe.Pointer 61 if ptr != nil { 62 u = runtime_registerWeakPointer(unsafe.Pointer(ptr)) 63 } 64 runtime.KeepAlive(ptr) 65 return Pointer[T]{u} 66} 67 68// Strong creates a strong pointer from the weak pointer. 69// Returns nil if the original value for the weak pointer was reclaimed by 70// the garbage collector. 71// If a weak pointer points to an object with a finalizer, then Strong will 72// return nil as soon as the object's finalizer is queued for execution. 73func (p Pointer[T]) Strong() *T { 74 return (*T)(runtime_makeStrongFromWeak(p.u)) 75} 76 77// Implemented in runtime. 78 79//go:linkname runtime_registerWeakPointer 80func runtime_registerWeakPointer(unsafe.Pointer) unsafe.Pointer 81 82//go:linkname runtime_makeStrongFromWeak 83func runtime_makeStrongFromWeak(unsafe.Pointer) unsafe.Pointer 84