github.com/hslam/atomic@v1.0.0/bytes.go (about) 1 // Copyright (c) 2020 Meng Huang (mhboy@outlook.com) 2 // This package is licensed under a MIT license that can be found in the LICENSE file. 3 4 package atomic 5 6 import ( 7 "unsafe" 8 ) 9 10 // bytesEqual reports whether a and b 11 // are the same length and contain the same bytes. 12 // A nil argument is equivalent to an empty slice. 13 func bytesEqual(a, b []byte) bool { 14 // Neither cmd/compile nor gccgo allocates for these string conversions. 15 return *(*string)(unsafe.Pointer(&a)) == *(*string)(unsafe.Pointer(&b)) 16 } 17 18 // Bytes represents an []byte. 19 type Bytes struct { 20 v Value 21 } 22 23 // NewBytes returns a new Bytes. 24 func NewBytes(val []byte) *Bytes { 25 addr := &Bytes{} 26 addr.Store(val) 27 return addr 28 } 29 30 // Swap atomically stores new into *addr and returns the previous *addr value. 31 func (addr *Bytes) Swap(new []byte) (old []byte) { 32 for { 33 load := addr.v.Load() 34 if addr.v.compareAndSwap(load, new) { 35 return load.([]byte) 36 } 37 } 38 } 39 40 // CompareAndSwap executes the compare-and-swap operation for an []byte value. 41 func (addr *Bytes) CompareAndSwap(old, new []byte) (swapped bool) { 42 load := addr.v.Load() 43 if !bytesEqual(old, load.([]byte)) { 44 return false 45 } 46 return addr.v.compareAndSwap(load, new) 47 } 48 49 // Add atomically adds delta to *addr and returns the new value. 50 func (addr *Bytes) Add(delta []byte) (new []byte) { 51 for { 52 old := addr.v.Load() 53 new = append(old.([]byte), delta...) 54 if addr.v.compareAndSwap(old, new) { 55 return 56 } 57 } 58 } 59 60 // Load atomically loads *addr. 61 func (addr *Bytes) Load() (val []byte) { 62 v := addr.v.Load() 63 if v == nil { 64 return nil 65 } 66 return v.([]byte) 67 } 68 69 // Store atomically stores val into *addr. 70 func (addr *Bytes) Store(val []byte) { 71 addr.v.Store(val) 72 }