2020-11-07 05:14:29 +00:00
|
|
|
package system
|
|
|
|
|
|
|
|
import (
|
2020-12-25 19:21:09 +00:00
|
|
|
"context"
|
2020-12-25 21:32:41 +00:00
|
|
|
"fmt"
|
2020-11-07 06:22:33 +00:00
|
|
|
"sync"
|
2020-11-07 05:14:29 +00:00
|
|
|
"sync/atomic"
|
2020-12-25 19:21:09 +00:00
|
|
|
"time"
|
2020-11-07 05:14:29 +00:00
|
|
|
)
|
|
|
|
|
2020-12-25 19:21:09 +00:00
|
|
|
// Runs a given work function every "d" duration until the provided context is canceled.
|
|
|
|
func Every(ctx context.Context, d time.Duration, work func(t time.Time)) {
|
|
|
|
ticker := time.NewTicker(d)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
case t := <-ticker.C:
|
|
|
|
work(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2020-12-25 21:32:41 +00:00
|
|
|
func FormatBytes(b int64) string {
|
|
|
|
if b < 1024 {
|
|
|
|
return fmt.Sprintf("%d B", b)
|
|
|
|
}
|
|
|
|
div, exp := int64(1024), 0
|
|
|
|
for n := b / 1024; n >= 1024; n /= 1024 {
|
|
|
|
div *= 1024
|
|
|
|
exp++
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp])
|
|
|
|
}
|
|
|
|
|
2020-11-07 05:14:29 +00:00
|
|
|
type AtomicBool struct {
|
|
|
|
flag uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ab *AtomicBool) Set(v bool) {
|
|
|
|
i := 0
|
|
|
|
if v {
|
|
|
|
i = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
atomic.StoreUint32(&ab.flag, uint32(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ab *AtomicBool) Get() bool {
|
|
|
|
return atomic.LoadUint32(&ab.flag) == 1
|
|
|
|
}
|
|
|
|
|
|
|
|
// AtomicString allows for reading/writing to a given struct field without having to worry
|
|
|
|
// about a potential race condition scenario. Under the hood it uses a simple sync.RWMutex
|
|
|
|
// to control access to the value.
|
|
|
|
type AtomicString struct {
|
2020-11-07 06:22:33 +00:00
|
|
|
v string
|
|
|
|
mu sync.RWMutex
|
2020-11-07 05:14:29 +00:00
|
|
|
}
|
|
|
|
|
2020-12-25 19:21:09 +00:00
|
|
|
func NewAtomicString(v string) AtomicString {
|
|
|
|
return AtomicString{v: v}
|
2020-11-07 05:14:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stores the string value passed atomically.
|
|
|
|
func (as *AtomicString) Store(v string) {
|
2020-11-07 06:22:33 +00:00
|
|
|
as.mu.Lock()
|
|
|
|
as.v = v
|
|
|
|
as.mu.Unlock()
|
2020-11-07 05:14:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Loads the string value and returns it.
|
|
|
|
func (as *AtomicString) Load() string {
|
2020-11-07 06:22:33 +00:00
|
|
|
as.mu.RLock()
|
|
|
|
defer as.mu.RUnlock()
|
|
|
|
return as.v
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AtomicString) UnmarshalText(b []byte) error {
|
|
|
|
as.Store(string(b))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-25 19:21:09 +00:00
|
|
|
//goland:noinspection GoVetCopyLock
|
|
|
|
func (as AtomicString) MarshalText() ([]byte, error) {
|
2020-11-07 06:22:33 +00:00
|
|
|
return []byte(as.Load()), nil
|
2020-11-07 05:14:29 +00:00
|
|
|
}
|