aboutsummaryrefslogtreecommitdiff
path: root/src/weak/pointer.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2024-11-15 20:42:32 +0000
committerGopher Robot <gobot@golang.org>2024-11-18 22:29:23 +0000
commita65f1a467ff6a10dc6688f292dfa8a2e08cc1eb4 (patch)
tree4ca29ec30c468aa3a7c2fe3ffd63a9e8d18f4389 /src/weak/pointer.go
parent5e82cba9bdf45d81da549477d172f6b5e23106d4 (diff)
downloadgo-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.go62
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