github.com/andy2046/gopie@v0.7.0/pkg/dll/amr.go (about)

     1  package dll
     2  
     3  import (
     4  	"sync/atomic"
     5  	"unsafe"
     6  )
     7  
     8  type (
     9  	atomicMarkableReference struct {
    10  		pair *pair
    11  	}
    12  
    13  	pair struct {
    14  		reference *Element
    15  		mark      bool
    16  	}
    17  )
    18  
    19  func newAtomicMarkableReference(initialRef *Element, initialMark bool) *atomicMarkableReference {
    20  	return &atomicMarkableReference{
    21  		&pair{
    22  			reference: initialRef,
    23  			mark:      initialMark,
    24  		},
    25  	}
    26  }
    27  
    28  func (amr *atomicMarkableReference) getPair() *pair {
    29  	return (*pair)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&amr.pair))))
    30  }
    31  
    32  func (amr *atomicMarkableReference) getReference() *Element {
    33  	p := amr.getPair()
    34  	return p.reference
    35  }
    36  
    37  func (amr *atomicMarkableReference) isMarked() bool {
    38  	p := amr.getPair()
    39  	return p.mark
    40  }
    41  
    42  func (amr *atomicMarkableReference) get() (bool, *Element) {
    43  	p := amr.getPair()
    44  	return p.mark, p.reference
    45  }
    46  
    47  func (amr *atomicMarkableReference) compareAndSet(expectedReference *Element,
    48  	newReference *Element,
    49  	expectedMark bool,
    50  	newMark bool) bool {
    51  	current := amr.getPair()
    52  	val := &pair{newReference, newMark}
    53  
    54  	return expectedReference == current.reference &&
    55  		expectedMark == current.mark &&
    56  		((newReference == current.reference &&
    57  			newMark == current.mark) ||
    58  			amr.casPair(current, val))
    59  }
    60  
    61  func (amr *atomicMarkableReference) tryMark(expectedReference *Element, newMark bool) bool {
    62  	current := amr.getPair()
    63  	val := &pair{expectedReference, newMark}
    64  	return expectedReference == current.reference &&
    65  		(newMark == current.mark ||
    66  			amr.casPair(current, val))
    67  }
    68  
    69  func (amr *atomicMarkableReference) casPair(cmp *pair, val *pair) bool {
    70  	return atomic.CompareAndSwapPointer(
    71  		(*unsafe.Pointer)(unsafe.Pointer(&amr.pair)),
    72  		unsafe.Pointer(cmp),
    73  		unsafe.Pointer(val))
    74  }