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  }