1package atomic
2
3import "sync"
4
5type SyncVal struct {
6	val  interface{}
7	lock sync.RWMutex
8}
9
10// NewSyncVal creates a new instance of SyncVal
11func NewSyncVal(val interface{}) *SyncVal {
12	return &SyncVal{val: val}
13}
14
15// Set updates the value of SyncVal with the passed argument
16func (sv *SyncVal) Set(val interface{}) {
17	sv.lock.Lock()
18	sv.val = val
19	sv.lock.Unlock()
20}
21
22// Get returns the value inside the SyncVal
23func (sv *SyncVal) Get() interface{} {
24	sv.lock.RLock()
25	val := sv.val
26	sv.lock.RUnlock()
27	return val
28}
29
30// GetSyncedVia returns the value returned by the function f.
31func (sv *SyncVal) GetSyncedVia(f func(interface{}) (interface{}, error)) (interface{}, error) {
32	sv.lock.RLock()
33	defer sv.lock.RUnlock()
34
35	val, err := f(sv.val)
36	return val, err
37}
38
39// Update gets a function and passes the value of SyncVal to it.
40// If the resulting err is nil, it will update the value of SyncVal.
41// It will return the resulting error to the caller.
42func (sv *SyncVal) Update(f func(interface{}) (interface{}, error)) error {
43	sv.lock.Lock()
44	defer sv.lock.Unlock()
45
46	val, err := f(sv.val)
47	if err == nil {
48		sv.val = val
49	}
50	return err
51}
52