85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
package blockstm
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type ErrReadError struct {
|
|
BlockingTxn TxnIndex
|
|
}
|
|
|
|
func (e ErrReadError) Error() string {
|
|
return fmt.Sprintf("read error: blocked by txn %d", e.BlockingTxn)
|
|
}
|
|
|
|
// StoreMin implements a compare-and-swap operation that stores the minimum of the current value and the given value.
|
|
func StoreMin(a *atomic.Uint64, b uint64) {
|
|
for {
|
|
old := a.Load()
|
|
if old <= b {
|
|
return
|
|
}
|
|
if a.CompareAndSwap(old, b) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// DecrAtomic decreases the atomic value by 1
|
|
func DecrAtomic(a *atomic.Uint64) {
|
|
a.Add(^uint64(0))
|
|
}
|
|
|
|
// IncrAtomic increases the atomic value by 1
|
|
func IncrAtomic(a *atomic.Uint64) {
|
|
a.Add(1)
|
|
}
|
|
|
|
// FetchIncr increases the atomic value by 1 and returns the old value
|
|
func FetchIncr(a *atomic.Uint64) uint64 {
|
|
return a.Add(1) - 1
|
|
}
|
|
|
|
// DiffOrderedList compares two ordered lists
|
|
// callback arguments: (value, is_new)
|
|
func DiffOrderedList(old, new []Key, callback func(Key, bool) bool) {
|
|
i, j := 0, 0
|
|
for i < len(old) && j < len(new) {
|
|
switch bytes.Compare(old[i], new[j]) {
|
|
case -1:
|
|
if !callback(old[i], false) {
|
|
return
|
|
}
|
|
i++
|
|
case 1:
|
|
if !callback(new[j], true) {
|
|
return
|
|
}
|
|
j++
|
|
default:
|
|
i++
|
|
j++
|
|
}
|
|
}
|
|
for ; i < len(old); i++ {
|
|
if !callback(old[i], false) {
|
|
return
|
|
}
|
|
}
|
|
for ; j < len(new); j++ {
|
|
if !callback(new[j], true) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// BytesBeyond returns if a is beyond b in specified iteration order
|
|
func BytesBeyond(a, b []byte, ascending bool) bool {
|
|
if ascending {
|
|
return bytes.Compare(a, b) > 0
|
|
}
|
|
return bytes.Compare(a, b) < 0
|
|
}
|