github.com/tursom/GoCollections@v0.3.10/lang/atomic/Atomic.go (about)

     1  /*
     2   * Copyright (c) 2022 tursom. All rights reserved.
     3   * Use of this source code is governed by a GPL-3
     4   * license that can be found in the LICENSE file.
     5   */
     6  
     7  package atomic
     8  
     9  import (
    10  	"sync/atomic"
    11  	"unsafe"
    12  
    13  	"github.com/tursom/GoCollections/lang"
    14  )
    15  
    16  type (
    17  	Atomic[T any] interface {
    18  		Swap(new T) (old T)
    19  		CompareAndSwap(old, new T) (swapped bool)
    20  		Load() (val T)
    21  		Store(val T)
    22  	}
    23  
    24  	BitSet interface {
    25  		lang.BitSet
    26  		CompareAndSwapBit(bit int, old, new bool) (swapped bool)
    27  	}
    28  
    29  	Atomizer[T any] interface {
    30  		Swap() func(addr *T, new T) (old T)
    31  		CompareAndSwap() func(addr *T, old, new T) (swapped bool)
    32  		Load() func(addr *T) (val T)
    33  		Store() func(addr *T, val T)
    34  	}
    35  
    36  	atomizerImpl[T any] struct {
    37  		swap           func(addr *T, new T) (old T)
    38  		compareAndSwap func(addr *T, old, new T) (swapped bool)
    39  		load           func(addr *T) (val T)
    40  		store          func(addr *T, val T)
    41  	}
    42  )
    43  
    44  var (
    45  	int32Atomizer = &atomizerImpl[int32]{
    46  		SwapInt32,
    47  		CompareAndSwapInt32,
    48  		LoadInt32,
    49  		StoreInt32,
    50  	}
    51  	int64Atomizer = &atomizerImpl[int64]{
    52  		SwapInt64,
    53  		CompareAndSwapInt64,
    54  		LoadInt64,
    55  		StoreInt64,
    56  	}
    57  	uint32Atomizer = &atomizerImpl[uint32]{
    58  		SwapUInt32,
    59  		CompareAndSwapUInt32,
    60  		LoadUint32,
    61  		StoreUInt32,
    62  	}
    63  	uint64Atomizer = &atomizerImpl[uint64]{
    64  		SwapUInt64,
    65  		CompareAndSwapUInt64,
    66  		LoadUint64,
    67  		StoreUInt64,
    68  	}
    69  	pointerAtomizer = &atomizerImpl[unsafe.Pointer]{
    70  		atomic.SwapPointer,
    71  		atomic.CompareAndSwapPointer,
    72  		atomic.LoadPointer,
    73  		atomic.StorePointer,
    74  	}
    75  )
    76  
    77  func Int32Atomizer() Atomizer[int32] {
    78  	return int32Atomizer
    79  }
    80  
    81  func Int64Atomizer() Atomizer[int64] {
    82  	return int64Atomizer
    83  }
    84  
    85  func UInt32Atomizer() Atomizer[uint32] {
    86  	return uint32Atomizer
    87  }
    88  
    89  func UInt64Atomizer() Atomizer[uint64] {
    90  	return uint64Atomizer
    91  }
    92  
    93  func PointerAtomizer() Atomizer[unsafe.Pointer] {
    94  	return pointerAtomizer
    95  }
    96  
    97  func GetAtomizer[T any]() Atomizer[*T] {
    98  	return (*atomizerImpl[*T])(unsafe.Pointer(pointerAtomizer))
    99  }
   100  
   101  func (a *atomizerImpl[T]) Swap() func(addr *T, new T) (old T) {
   102  	return a.swap
   103  }
   104  
   105  func (a *atomizerImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) {
   106  	return a.compareAndSwap
   107  }
   108  
   109  func (a *atomizerImpl[T]) Load() func(addr *T) (val T) {
   110  	return a.load
   111  }
   112  
   113  func (a *atomizerImpl[T]) Store() func(addr *T, val T) {
   114  	return a.store
   115  }
   116  
   117  func SwapInt32(addr *int32, new int32) (old int32) {
   118  	return atomic.SwapInt32(addr, new)
   119  }
   120  
   121  func SwapInt64(addr *int64, new int64) (old int64) {
   122  	return atomic.SwapInt64(addr, new)
   123  }
   124  
   125  func SwapUInt32(addr *uint32, new uint32) (old uint32) {
   126  	return atomic.SwapUint32(addr, new)
   127  }
   128  
   129  func SwapUInt64(addr *uint64, new uint64) (old uint64) {
   130  	return atomic.SwapUint64(addr, new)
   131  }
   132  
   133  func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) {
   134  	return atomic.SwapUintptr(addr, new)
   135  }
   136  
   137  func SwapUnsafePointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) {
   138  	return atomic.SwapPointer(addr, new)
   139  }
   140  
   141  func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) {
   142  	return atomic.CompareAndSwapInt32(addr, old, new)
   143  }
   144  
   145  func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool) {
   146  	return atomic.CompareAndSwapInt64(addr, old, new)
   147  }
   148  
   149  func CompareAndSwapUInt32(addr *uint32, old, new uint32) (swapped bool) {
   150  	return atomic.CompareAndSwapUint32(addr, old, new)
   151  }
   152  
   153  func CompareAndSwapUInt64(addr *uint64, old, new uint64) (swapped bool) {
   154  	return atomic.CompareAndSwapUint64(addr, old, new)
   155  }
   156  
   157  func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool) {
   158  	return atomic.CompareAndSwapUintptr(addr, old, new)
   159  }
   160  
   161  func CompareAndSwapUnsafePointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
   162  	return atomic.CompareAndSwapPointer(addr, old, new)
   163  }
   164  
   165  func AddInt32(addr *int32, delta int32) (new int32) {
   166  	return atomic.AddInt32(addr, delta)
   167  }
   168  
   169  func AddUInt32(addr *uint32, delta uint32) (new uint32) {
   170  	return atomic.AddUint32(addr, delta)
   171  }
   172  
   173  func AddInt64(addr *int64, delta int64) (new int64) {
   174  	return atomic.AddInt64(addr, delta)
   175  }
   176  
   177  func AddUInt64(addr *uint64, delta uint64) (new uint64) {
   178  	return atomic.AddUint64(addr, delta)
   179  }
   180  
   181  func AddUintptr(addr *uintptr, delta uintptr) (new uintptr) {
   182  	return atomic.AddUintptr(addr, delta)
   183  }
   184  
   185  func LoadInt32(addr *int32) (val int32) {
   186  	return atomic.LoadInt32(addr)
   187  }
   188  
   189  func LoadInt64(addr *int64) (val int64) {
   190  	return atomic.LoadInt64(addr)
   191  }
   192  
   193  func LoadUint32(addr *uint32) (val uint32) {
   194  	return atomic.LoadUint32(addr)
   195  }
   196  
   197  func LoadUint64(addr *uint64) (val uint64) {
   198  	return atomic.LoadUint64(addr)
   199  }
   200  
   201  func LoadUintptr(addr *uintptr) (val uintptr) {
   202  	return atomic.LoadUintptr(addr)
   203  }
   204  
   205  func LoadUnsafePointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
   206  	return atomic.LoadPointer(addr)
   207  }
   208  
   209  func StoreInt32(addr *int32, val int32) {
   210  	atomic.StoreInt32(addr, val)
   211  }
   212  
   213  func StoreInt64(addr *int64, val int64) {
   214  	atomic.StoreInt64(addr, val)
   215  }
   216  
   217  func StoreUInt32(addr *uint32, val uint32) {
   218  	atomic.StoreUint32(addr, val)
   219  }
   220  
   221  func StoreUInt64(addr *uint64, val uint64) {
   222  	atomic.StoreUint64(addr, val)
   223  }
   224  
   225  func StoreUintptr(addr *uintptr, val uintptr) {
   226  	atomic.StoreUintptr(addr, val)
   227  }
   228  
   229  func StoreUnsafePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
   230  	atomic.StorePointer(addr, val)
   231  }
   232  
   233  func SetBit[T int32 | int64 | uint32 | uint64](cas func(p *T, old, new T) bool, p *T, bit int, up bool) bool {
   234  	location := T(1) << bit
   235  	var old T
   236  	for {
   237  		old = *p
   238  		var newValue T
   239  		if up {
   240  			newValue = old | location
   241  		} else {
   242  			newValue = old & ^location
   243  		}
   244  		if cas(p, old, newValue) {
   245  			break
   246  		}
   247  	}
   248  	return old&location != 0
   249  }
   250  
   251  func SetBitInt32(p *int32, bit int, up bool) bool {
   252  	return SetBit(CompareAndSwapInt32, p, bit, up)
   253  }
   254  
   255  func SetBitInt64(p *int64, bit int, up bool) bool {
   256  	return SetBit(CompareAndSwapInt64, p, bit, up)
   257  }
   258  
   259  func SetBitUInt32(p *uint32, bit int, up bool) bool {
   260  	return SetBit(CompareAndSwapUInt32, p, bit, up)
   261  }
   262  
   263  func SetBitUInt64(p *uint32, bit int, up bool) bool {
   264  	return SetBit(CompareAndSwapUInt32, p, bit, up)
   265  }
   266  
   267  func CompareAndSwapBit[T int32 | int64 | uint32 | uint64](cas func(p *T, old, new T) bool, p *T, bit int, old, new bool) bool {
   268  	location := T(1) << bit
   269  	oldValue := *p
   270  	if old {
   271  		oldValue = oldValue | location
   272  	} else {
   273  		oldValue = oldValue & ^location
   274  	}
   275  	var newValue T
   276  	if new {
   277  		newValue = oldValue | location
   278  	} else {
   279  		newValue = oldValue & ^location
   280  	}
   281  	return cas(p, oldValue, newValue)
   282  }
   283  
   284  func CompareAndSwapBitInt32(p *int32, bit int, old, new bool) bool {
   285  	return CompareAndSwapBit(CompareAndSwapInt32, p, bit, old, new)
   286  }
   287  
   288  func CompareAndSwapBitInt64(p *int64, bit int, old, new bool) bool {
   289  	return CompareAndSwapBit(CompareAndSwapInt64, p, bit, old, new)
   290  }
   291  
   292  func CompareAndSwapBitUInt32(p *uint32, bit int, old, new bool) bool {
   293  	return CompareAndSwapBit(CompareAndSwapUInt32, p, bit, old, new)
   294  }
   295  
   296  func CompareAndSwapBitUInt64(p *uint64, bit int, old, new bool) bool {
   297  	return CompareAndSwapBit(CompareAndSwapUInt64, p, bit, old, new)
   298  }