summaryrefslogtreecommitdiffstats
path: root/src/sync/oncefunc.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:25:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:25:22 +0000
commitf6ad4dcef54c5ce997a4bad5a6d86de229015700 (patch)
tree7cfa4e31ace5c2bd95c72b154d15af494b2bcbef /src/sync/oncefunc.go
parentInitial commit. (diff)
downloadgolang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.tar.xz
golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.zip
Adding upstream version 1.22.1.upstream/1.22.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/sync/oncefunc.go')
-rw-r--r--src/sync/oncefunc.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/sync/oncefunc.go b/src/sync/oncefunc.go
new file mode 100644
index 0000000..db28628
--- /dev/null
+++ b/src/sync/oncefunc.go
@@ -0,0 +1,100 @@
+// Copyright 2022 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 sync
+
+// OnceFunc returns a function that invokes f only once. The returned function
+// may be called concurrently.
+//
+// If f panics, the returned function will panic with the same value on every call.
+func OnceFunc(f func()) func() {
+ var (
+ once Once
+ valid bool
+ p any
+ )
+ // Construct the inner closure just once to reduce costs on the fast path.
+ g := func() {
+ defer func() {
+ p = recover()
+ if !valid {
+ // Re-panic immediately so on the first call the user gets a
+ // complete stack trace into f.
+ panic(p)
+ }
+ }()
+ f()
+ f = nil // Do not keep f alive after invoking it.
+ valid = true // Set only if f does not panic.
+ }
+ return func() {
+ once.Do(g)
+ if !valid {
+ panic(p)
+ }
+ }
+}
+
+// OnceValue returns a function that invokes f only once and returns the value
+// returned by f. The returned function may be called concurrently.
+//
+// If f panics, the returned function will panic with the same value on every call.
+func OnceValue[T any](f func() T) func() T {
+ var (
+ once Once
+ valid bool
+ p any
+ result T
+ )
+ g := func() {
+ defer func() {
+ p = recover()
+ if !valid {
+ panic(p)
+ }
+ }()
+ result = f()
+ f = nil
+ valid = true
+ }
+ return func() T {
+ once.Do(g)
+ if !valid {
+ panic(p)
+ }
+ return result
+ }
+}
+
+// OnceValues returns a function that invokes f only once and returns the values
+// returned by f. The returned function may be called concurrently.
+//
+// If f panics, the returned function will panic with the same value on every call.
+func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
+ var (
+ once Once
+ valid bool
+ p any
+ r1 T1
+ r2 T2
+ )
+ g := func() {
+ defer func() {
+ p = recover()
+ if !valid {
+ panic(p)
+ }
+ }()
+ r1, r2 = f()
+ f = nil
+ valid = true
+ }
+ return func() (T1, T2) {
+ once.Do(g)
+ if !valid {
+ panic(p)
+ }
+ return r1, r2
+ }
+}