2018-12-14 20:49:18 -06:00
|
|
|
package util
|
2017-12-28 22:16:20 -06:00
|
|
|
|
|
|
|
// These are misc. utility functions that didn't really fit anywhere else
|
|
|
|
|
|
|
|
import "runtime"
|
2019-07-27 18:10:32 -05:00
|
|
|
import "sync"
|
2019-02-02 22:18:55 -06:00
|
|
|
import "time"
|
2018-01-04 22:37:51 +00:00
|
|
|
|
2018-06-10 18:03:28 -05:00
|
|
|
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
2018-12-14 20:49:18 -06:00
|
|
|
func Yield() {
|
2018-01-04 22:37:51 +00:00
|
|
|
runtime.Gosched()
|
2017-12-28 22:16:20 -06:00
|
|
|
}
|
|
|
|
|
2018-06-10 18:03:28 -05:00
|
|
|
// A wrapper around runtime.LockOSThread() so it doesn't need to be imported elsewhere.
|
2018-12-14 20:49:18 -06:00
|
|
|
func LockThread() {
|
2018-01-04 22:37:51 +00:00
|
|
|
runtime.LockOSThread()
|
2017-12-28 22:16:20 -06:00
|
|
|
}
|
|
|
|
|
2018-06-10 18:03:28 -05:00
|
|
|
// A wrapper around runtime.UnlockOSThread() so it doesn't need to be imported elsewhere.
|
2018-12-14 20:49:18 -06:00
|
|
|
func UnlockThread() {
|
2018-01-04 22:37:51 +00:00
|
|
|
runtime.UnlockOSThread()
|
2017-12-28 22:16:20 -06:00
|
|
|
}
|
|
|
|
|
2018-06-10 18:03:28 -05:00
|
|
|
// This is used to buffer recently used slices of bytes, to prevent allocations in the hot loops.
|
2019-08-04 00:28:13 -05:00
|
|
|
var byteStore = sync.Pool{New: func() interface{} { return []byte(nil) }}
|
2017-12-28 22:16:20 -06:00
|
|
|
|
2019-07-27 18:10:32 -05:00
|
|
|
// Gets an empty slice from the byte store.
|
2018-12-14 20:49:18 -06:00
|
|
|
func GetBytes() []byte {
|
2019-08-04 00:28:13 -05:00
|
|
|
return byteStore.Get().([]byte)[:0]
|
2017-12-28 22:16:20 -06:00
|
|
|
}
|
|
|
|
|
2019-07-27 18:10:32 -05:00
|
|
|
// Puts a slice in the store.
|
2018-12-14 20:49:18 -06:00
|
|
|
func PutBytes(bs []byte) {
|
2019-08-04 00:28:13 -05:00
|
|
|
byteStore.Put(bs)
|
2017-12-28 22:16:20 -06:00
|
|
|
}
|
2019-02-02 22:18:55 -06:00
|
|
|
|
|
|
|
// This is a workaround to go's broken timer implementation
|
|
|
|
func TimerStop(t *time.Timer) bool {
|
2019-04-26 22:42:05 -05:00
|
|
|
stopped := t.Stop()
|
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
default:
|
2019-02-02 22:18:55 -06:00
|
|
|
}
|
2019-04-26 22:42:05 -05:00
|
|
|
return stopped
|
2019-02-02 22:18:55 -06:00
|
|
|
}
|
2019-02-26 21:07:56 -06: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
|
|
|
|
}
|
|
|
|
}
|
2019-03-04 18:41:32 +00:00
|
|
|
|
|
|
|
// 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 {
|
2019-03-08 10:26:46 +00:00
|
|
|
if !mb[x] {
|
2019-03-04 18:41:32 +00:00
|
|
|
ab = append(ab, x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ab
|
|
|
|
}
|