diff options
| author | Michael Anthony Knyszek <mknyszek@google.com> | 2024-11-15 20:42:32 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-11-18 22:29:23 +0000 |
| commit | a65f1a467ff6a10dc6688f292dfa8a2e08cc1eb4 (patch) | |
| tree | 4ca29ec30c468aa3a7c2fe3ffd63a9e8d18f4389 /src/weak/pointer.go | |
| parent | 5e82cba9bdf45d81da549477d172f6b5e23106d4 (diff) | |
| download | go-a65f1a467ff6a10dc6688f292dfa8a2e08cc1eb4.tar.xz | |
weak: move internal/weak to weak, and update according to proposal
The updates are:
- API documentation changes.
- Removal of the old package documentation discouraging linkname.
- Addition of new package documentation with some advice.
- Renaming of weak.Pointer.Strong -> weak.Pointer.Value.
Fixes #67552.
Change-Id: Ifad7e629b6d339dacaf2ca37b459d7f903e31bf8
Reviewed-on: https://go-review.googlesource.com/c/go/+/628455
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/weak/pointer.go')
| -rw-r--r-- | src/weak/pointer.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/weak/pointer.go b/src/weak/pointer.go new file mode 100644 index 0000000000..f6d20530ab --- /dev/null +++ b/src/weak/pointer.go @@ -0,0 +1,62 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package weak + +import ( + "internal/abi" + "runtime" + "unsafe" +) + +// Pointer is a weak pointer to a value of type T. +// +// Two Pointer values compare equal if the pointers +// that they were created from compare equal. This property is retained even +// after the object referenced by the pointer used to create a weak reference +// is reclaimed. +// +// If multiple weak pointers are made to different offsets within same object +// (for example, pointers to different fields of the same struct), those pointers +// will not compare equal. +// If a weak pointer is created from an object that becomes unreachable, but is +// then resurrected due to a finalizer, that weak pointer will not compare equal +// with weak pointers created after resurrection. +// +// Calling Make with a nil pointer returns a weak pointer whose Value method +// always returns nil. The zero value of a Pointer behaves as if it was created +// by passing nil to Make and compares equal with such pointers. +type Pointer[T any] struct { + u unsafe.Pointer +} + +// Make creates a weak pointer from a strong pointer to some value of type T. +func Make[T any](ptr *T) Pointer[T] { + // Explicitly force ptr to escape to the heap. + ptr = abi.Escape(ptr) + + var u unsafe.Pointer + if ptr != nil { + u = runtime_registerWeakPointer(unsafe.Pointer(ptr)) + } + runtime.KeepAlive(ptr) + return Pointer[T]{u} +} + +// Value returns the original pointer used to create the weak pointer. +// It returns nil if the value pointed to by the original pointer was reclaimed by +// the garbage collector. +// If a weak pointer points to an object with a finalizer, then Value will +// return nil as soon as the object's finalizer is queued for execution. +func (p Pointer[T]) Value() *T { + return (*T)(runtime_makeStrongFromWeak(p.u)) +} + +// Implemented in runtime. + +//go:linkname runtime_registerWeakPointer +func runtime_registerWeakPointer(unsafe.Pointer) unsafe.Pointer + +//go:linkname runtime_makeStrongFromWeak +func runtime_makeStrongFromWeak(unsafe.Pointer) unsafe.Pointer |
