github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/atomickit/uint32.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package atomickit
     7  
     8  import (
     9  	"strconv"
    10  	"sync/atomic"
    11  )
    12  
    13  func NewUint32(v uint32) Uint32 {
    14  	return Uint32{v}
    15  }
    16  
    17  type Uint32 struct {
    18  	v uint32
    19  }
    20  
    21  func (p *Uint32) Load() uint32 {
    22  	return atomic.LoadUint32(&p.v)
    23  }
    24  
    25  func (p *Uint32) Store(v uint32) {
    26  	atomic.StoreUint32(&p.v, v)
    27  }
    28  
    29  func (p *Uint32) Swap(v uint32) uint32 {
    30  	return atomic.SwapUint32(&p.v, v)
    31  }
    32  
    33  func (p *Uint32) CompareAndSwap(old, new uint32) bool {
    34  	return atomic.CompareAndSwapUint32(&p.v, old, new)
    35  }
    36  
    37  func (p *Uint32) Add(v uint32) uint32 {
    38  	return atomic.AddUint32(&p.v, v)
    39  }
    40  
    41  func (p *Uint32) Sub(v uint32) uint32 {
    42  	return p.Add(^(v - 1))
    43  }
    44  
    45  func (p *Uint32) String() string {
    46  	return strconv.FormatUint(uint64(p.Load()), 10)
    47  }
    48  
    49  func (p *Uint32) SetBits(v uint32) uint32 {
    50  	for {
    51  		switch x := p.Load(); {
    52  		case x & v == v:
    53  			return x
    54  		case p.CompareAndSwap(x, x|v):
    55  			return x|v
    56  		}
    57  	}
    58  }
    59  
    60  func (p *Uint32) TrySetBits(v uint32, all bool) bool {
    61  	for {
    62  		x := p.Load()
    63  		switch {
    64  		case x & v == 0:
    65  		case all:
    66  			return false
    67  		case x & v == v:
    68  			return false
    69  		}
    70  		if p.CompareAndSwap(x, x|v) {
    71  			return true
    72  		}
    73  	}
    74  }
    75  
    76  func (p *Uint32) UnsetBits(v uint32) uint32 {
    77  	for {
    78  		switch x := p.Load(); {
    79  		case x & v == 0:
    80  			return x
    81  		case p.CompareAndSwap(x, x&^v):
    82  			return x&^v
    83  		}
    84  	}
    85  }
    86  
    87  func (p *Uint32) TryUnsetBits(v uint32, all bool) bool {
    88  	for {
    89  		x := p.Load()
    90  		switch {
    91  		case x & v == 0:
    92  			return false
    93  		case x & v == v:
    94  		case all:
    95  			return false
    96  		}
    97  		if p.CompareAndSwap(x, x&^v) {
    98  			return true
    99  		}
   100  	}
   101  }
   102  
   103  func (p *Uint32) CompareAndSub(v uint32) bool {
   104  	for {
   105  		switch x := p.Load(); {
   106  		case x < v:
   107  			return false
   108  		case p.CompareAndSwap(x, x-v):
   109  			return true
   110  		}
   111  	}
   112  }
   113  
   114  func (p *Uint32) SetLesser(v uint32) uint32 {
   115  	for {
   116  		switch x := p.Load(); {
   117  		case x <= v:
   118  			return x
   119  		case p.CompareAndSwap(x, v):
   120  			return v
   121  		}
   122  	}
   123  }
   124  
   125  func (p *Uint32) SetGreater(v uint32) uint32 {
   126  	for {
   127  		switch x := p.Load(); {
   128  		case x >= v:
   129  			return x
   130  		case p.CompareAndSwap(x, v):
   131  			return v
   132  		}
   133  	}
   134  }
   135  
   136  func (p *Uint32) CompareAndSetBits(maskOut, deny, v uint32) bool {
   137  	for {
   138  		x := p.Load()
   139  		x2 := x &^ maskOut
   140  		switch {
   141  		case x2 & deny != 0:
   142  			return false
   143  		case x2 & v != 0:
   144  			return false
   145  		}
   146  		if p.CompareAndSwap(x, x|v) {
   147  			return true
   148  		}
   149  	}
   150  }