5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-12-25 04:55:44 +00:00
yggdrasil-go/src/util/util.go

96 lines
2.2 KiB
Go
Raw Normal View History

package util
2017-12-29 04:16:20 +00:00
// These are misc. utility functions that didn't really fit anywhere else
import "runtime"
import "time"
2018-01-04 22:37:51 +00:00
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
func Yield() {
2018-01-04 22:37:51 +00:00
runtime.Gosched()
2017-12-29 04:16:20 +00:00
}
// A wrapper around runtime.LockOSThread() so it doesn't need to be imported elsewhere.
func LockThread() {
2018-01-04 22:37:51 +00:00
runtime.LockOSThread()
2017-12-29 04:16:20 +00:00
}
// A wrapper around runtime.UnlockOSThread() so it doesn't need to be imported elsewhere.
func UnlockThread() {
2018-01-04 22:37:51 +00:00
runtime.UnlockOSThread()
2017-12-29 04:16:20 +00:00
}
// This is used to buffer recently used slices of bytes, to prevent allocations in the hot loops.
// It's used like a sync.Pool, but with a fixed size and typechecked without type casts to/from interface{} (which were making the profiles look ugly).
2017-12-29 04:16:20 +00:00
var byteStore chan []byte
func init() {
byteStore = make(chan []byte, 32)
2017-12-29 04:16:20 +00:00
}
// Gets an empty slice from the byte store, if one is available, or else returns a new nil slice.
func GetBytes() []byte {
2018-01-04 22:37:51 +00:00
select {
case bs := <-byteStore:
return bs[:0]
default:
return nil
}
2017-12-29 04:16:20 +00:00
}
// Puts a slice in the store, if there's room, or else returns and lets the slice get collected.
func PutBytes(bs []byte) {
2018-01-04 22:37:51 +00:00
select {
case byteStore <- bs:
default:
}
2017-12-29 04:16:20 +00:00
}
// This is a workaround to go's broken timer implementation
func TimerStop(t *time.Timer) bool {
if !t.Stop() {
select {
case <-t.C:
default:
}
}
return true
}
2019-02-27 03:07:56 +00:00
// Run a blocking function with a timeout.
// Returns true if the function returns.
// Returns false if the timer fires.
// The blocked function remains blocked--the caller is responsible for somehow killing it.
func FuncTimeout(f func(), timeout time.Duration) bool {
success := make(chan struct{})
go func() {
defer close(success)
f()
}()
timer := time.NewTimer(timeout)
defer TimerStop(timer)
select {
case <-success:
return true
case <-timer.C:
return false
}
}
// This calculates the difference between two arrays and returns items
// that appear in A but not in B - useful somewhat when reconfiguring
// and working out what configuration items changed
func Difference(a, b []string) []string {
ab := []string{}
mb := map[string]bool{}
for _, x := range b {
mb[x] = true
}
for _, x := range a {
if _, ok := mb[x]; !ok {
ab = append(ab, x)
}
}
return ab
}