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  

View as plain text