|
| 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 |
0 commit comments