Source file src/internal/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  /*
     6  The weak package is a package for managing weak pointers.
     7  
     8  Weak pointers are pointers that explicitly do not keep a value live and
     9  must be queried for a regular Go pointer.
    10  The result of such a query may be observed as nil at any point after a
    11  weakly-pointed-to object becomes eligible for reclamation by the garbage
    12  collector.
    13  More specifically, weak pointers become nil as soon as the garbage collector
    14  identifies that the object is unreachable, before it is made reachable
    15  again by a finalizer.
    16  In terms of the C# language, these semantics are roughly equivalent to the
    17  the semantics of "short" weak references.
    18  In terms of the Java language, these semantics are roughly equivalent to the
    19  semantics of the WeakReference type.
    20  
    21  Using go:linkname to access this package and the functions it references
    22  is explicitly forbidden by the toolchain because the semantics of this
    23  package have not gone through the proposal process. By exposing this
    24  functionality, we risk locking in the existing semantics due to Hyrum's Law.
    25  
    26  If you believe you have a good use-case for weak references not already
    27  covered by the standard library, file a proposal issue at
    28  https://github.com/golang/go/issues instead of relying on this package.
    29  */
    30  package weak
    31  
    32  import (
    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.
    51  type 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.
    56  func 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.
    73  func (p Pointer[T]) Strong() *T {
    74  	return (*T)(runtime_makeStrongFromWeak(p.u))
    75  }
    76  
    77  // Implemented in runtime.
    78  
    79  //go:linkname runtime_registerWeakPointer
    80  func runtime_registerWeakPointer(unsafe.Pointer) unsafe.Pointer
    81  
    82  //go:linkname runtime_makeStrongFromWeak
    83  func runtime_makeStrongFromWeak(unsafe.Pointer) unsafe.Pointer
    84  

View as plain text