-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c635464
commit d59ac57
Showing
4 changed files
with
158 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//go:build go1.21 | ||
|
||
package common | ||
|
||
import ( | ||
"cmp" | ||
) | ||
|
||
func Min[T cmp.Ordered](x, y T) T { | ||
return min(x, y) | ||
} | ||
|
||
func Max[T cmp.Ordered](x, y T) T { | ||
return max(x, y) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
//go:build go1.20 && !go1.21 | ||
|
||
package common | ||
|
||
import "github.com/sagernet/sing/common/x/constraints" | ||
|
||
func Min[T constraints.Ordered](x, y T) T { | ||
if x < y { | ||
return x | ||
} | ||
return y | ||
} | ||
|
||
func Max[T constraints.Ordered](x, y T) T { | ||
if x < y { | ||
return y | ||
} | ||
return x | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//go:build go1.21 | ||
|
||
package common | ||
|
||
import "sync" | ||
|
||
// OnceFunc is a wrapper around sync.OnceFunc. | ||
func OnceFunc(f func()) func() { | ||
return sync.OnceFunc(f) | ||
} | ||
|
||
// OnceValue is a wrapper around sync.OnceValue. | ||
func OnceValue[T any](f func() T) func() T { | ||
return sync.OnceValue(f) | ||
} | ||
|
||
// OnceValues is a wrapper around sync.OnceValues. | ||
func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) { | ||
return sync.OnceValues(f) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// 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. | ||
|
||
//go:build go1.20 && !go1.21 | ||
|
||
package common | ||
|
||
import "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 sync.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 sync.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 sync.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 | ||
} | ||
} |