error.go (1350B)
1 package atomics 2 3 import ( 4 "sync/atomic" 5 "unsafe" 6 ) 7 8 // Error provides user-friendly means of performing atomic operations on error types. 9 type Error struct{ ptr unsafe.Pointer } 10 11 // NewError will return a new Error instance initialized with zero value. 12 func NewError() *Error { 13 var v error 14 return &Error{ 15 ptr: unsafe.Pointer(&v), 16 } 17 } 18 19 // Store will atomically store error value in address contained within v. 20 func (v *Error) Store(val error) { 21 atomic.StorePointer(&v.ptr, unsafe.Pointer(&val)) 22 } 23 24 // Load will atomically load error value at address contained within v. 25 func (v *Error) Load() error { 26 return *(*error)(atomic.LoadPointer(&v.ptr)) 27 } 28 29 // CAS performs a compare-and-swap for a(n) error value at address contained within v. 30 func (v *Error) CAS(cmp, swp error) bool { 31 for { 32 // Load current value at address 33 ptr := atomic.LoadPointer(&v.ptr) 34 cur := *(*error)(ptr) 35 36 // Perform comparison against current 37 if !(cur == cmp) { 38 return false 39 } 40 41 // Attempt to replace pointer 42 if atomic.CompareAndSwapPointer( 43 &v.ptr, 44 ptr, 45 unsafe.Pointer(&swp), 46 ) { 47 return true 48 } 49 } 50 } 51 52 // Swap atomically stores new error value into address contained within v, and returns previous value. 53 func (v *Error) Swap(swp error) error { 54 ptr := unsafe.Pointer(&swp) 55 ptr = atomic.SwapPointer(&v.ptr, ptr) 56 return *(*error)(ptr) 57 }