state.go (1478B)
1 package atomics 2 3 import "sync" 4 5 // State provides user-friendly means of performing atomic-like 6 // operations on a uint32 state, and allowing callbacks on successful 7 // state change. This is a bit of a misnomer being where it is, as it 8 // actually uses a mutex under-the-hood. 9 type State struct { 10 mutex sync.Mutex 11 state uint32 12 } 13 14 // Store will update State value safely within mutex lock. 15 func (st *State) Store(val uint32) { 16 st.mutex.Lock() 17 st.state = val 18 st.mutex.Unlock() 19 } 20 21 // Load will get value of State safely within mutex lock. 22 func (st *State) Load() uint32 { 23 st.mutex.Lock() 24 state := st.state 25 st.mutex.Unlock() 26 return state 27 } 28 29 // WithLock performs fn within State mutex lock, useful if you want 30 // to just use State's mutex for locking instead of creating another. 31 func (st *State) WithLock(fn func()) { 32 st.mutex.Lock() 33 defer st.mutex.Unlock() 34 fn() 35 } 36 37 // Update performs fn within State mutex lock, with the current state 38 // value provided as an argument, and return value used to update state. 39 func (st *State) Update(fn func(state uint32) uint32) { 40 st.mutex.Lock() 41 defer st.mutex.Unlock() 42 st.state = fn(st.state) 43 } 44 45 // CAS performs a compare-and-swap on State, calling fn on success. Success value is also returned. 46 func (st *State) CAS(cmp, swp uint32, fn func()) (ok bool) { 47 // Acquire lock 48 st.mutex.Lock() 49 defer st.mutex.Unlock() 50 51 // Perform CAS operation, fn() on success 52 if ok = (st.state == cmp); ok { 53 st.state = swp 54 fn() 55 } 56 57 return 58 }