update atmoic

This commit is contained in:
tursom 2022-12-03 19:13:29 +08:00
parent fed6847099
commit 7bca6fe5cf
17 changed files with 388 additions and 177 deletions

View File

@ -11,7 +11,7 @@ import (
"testing"
"time"
"github.com/tursom/GoCollections/util/unsafe"
"github.com/tursom/GoCollections/unsafe"
)
func TestPublisherMessageQueueNode_Sizeof(t *testing.T) {

15
encoding/hex/hex.go Normal file
View File

@ -0,0 +1,15 @@
package hex
import (
"encoding/hex"
"github.com/tursom/GoCollections/unsafe"
)
func EncodeToString[T any](arr []T) string {
return hex.EncodeToString(unsafe.AsBytes(arr))
}
func DecodeString(s string) ([]byte, error) {
return hex.DecodeString(s)
}

74
lang/Array.go Normal file
View File

@ -0,0 +1,74 @@
package lang
type (
Array[T any] []T
Int8Array Array[int32]
Int16Array Array[int32]
Int32Array Array[int32]
Int64Array Array[int64]
UInt8Array Array[uint32]
UInt16Array Array[uint32]
UInt32Array Array[uint32]
UInt64Array Array[uint64]
)
func (a Array[T]) Array() []T {
return a
}
func (a Int8Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 8
i := &a[arrIndex]
return SwapBit(i, bit%8, up)
}
func (a Int16Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 16
i := &a[arrIndex]
return SwapBit(i, bit%16, up)
}
func (a Int32Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 32
i := &a[arrIndex]
return SwapBit(i, bit%32, up)
}
func (a Int64Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 64
i := &a[arrIndex]
return SwapBit(i, bit%64, up)
}
func (a UInt8Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 8
i := &a[arrIndex]
return SwapBit(i, bit%8, up)
}
func (a UInt16Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 16
i := &a[arrIndex]
return SwapBit(i, bit%16, up)
}
func (a UInt32Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 32
i := &a[arrIndex]
return SwapBit(i, bit%32, up)
}
func (a UInt64Array) SetBit(bit int, up bool) (old bool) {
arrIndex := bit / 64
i := &a[arrIndex]
return SwapBit(i, bit%64, up)
}

View File

@ -8,7 +8,6 @@ package lang
import (
"reflect"
"unsafe"
)
func TypeName[T any]() string {
@ -54,11 +53,3 @@ func Cast[T any](v any) T {
return t
}
}
func ForceCast[T any](v unsafe.Pointer) *T {
if v == nil {
return nil
} else {
return (*T)(v)
}
}

View File

@ -12,3 +12,16 @@ type Number interface {
ToUInt64() UInt64
ToFloat64() Float64
}
func SwapBit[T int32 | int64 | uint32 | uint64](p *T, bit int, new bool) (old bool) {
location := T(1) << bit
oldValue := *p
var newValue T
if new {
newValue = oldValue | location
} else {
newValue = oldValue & ^location
}
*p = newValue
return oldValue&newValue != 0
}

View File

@ -6,111 +6,188 @@
package atomic
import "github.com/tursom/GoCollections/lang"
type (
Array[T any] struct {
atomic Atomic[T]
array []T
}
Int32Array struct {
Array[int32]
}
Int64Array struct {
Array[int64]
}
UInt32Array struct {
Array[uint32]
}
UInt64Array struct {
Array[uint64]
}
Array[T any] lang.Array[*T]
Int32Array lang.Array[Int32]
Int64Array lang.Array[Int64]
UInt32Array lang.Array[UInt32]
UInt64Array lang.Array[UInt64]
)
func NewArray[T any](size int) *Array[*T] {
return &Array[*T]{
atomic: GetAtomic[T](),
array: make([]*T, size),
}
func NewArray[T any](size int) Array[T] {
return make([]*T, size)
}
func CapArray[T any](array []*T) *Array[*T] {
return &Array[*T]{
atomic: GetAtomic[T](),
array: array,
}
func CapArray[T any](array []*T) Array[T] {
return array
}
func NewInt32Array(size int) *Int32Array {
return &Int32Array{
Array[int32]{
atomic: Int32F,
array: make([]int32, size),
},
}
func NewInt32Array(size int) Int32Array {
return make(Int32Array, size)
}
func NewInt64Array(size int) *Int64Array {
return &Int64Array{
Array[int64]{
atomic: Int64F,
array: make([]int64, size),
},
}
func NewInt64Array(size int) Int64Array {
return make(Int64Array, size)
}
func NewUInt32Array(size int) *UInt32Array {
return &UInt32Array{
Array[uint32]{
atomic: UInt32F,
array: make([]uint32, size),
},
}
func NewUInt32Array(size int) UInt32Array {
return make(UInt32Array, size)
}
func NewUInt64Array(size int) *UInt64Array {
return &UInt64Array{
Array[uint64]{
atomic: UInt64F,
array: make([]uint64, size),
},
}
func NewUInt64Array(size int) UInt64Array {
return make(UInt64Array, size)
}
func (a *Array[T]) Len() int {
return len(a.array)
func (a Array[T]) Len() int {
return len(a)
}
func (a *Array[T]) Array() []T {
return a.array
func (a Array[T]) Array() []*T {
return a
}
func (a *Array[T]) Get(index int) T {
return a.atomic.Load()(&a.array[index])
func (a Array[T]) Get(index int) *T {
return GetAtomizer[T]().Load()(&a[index])
}
func (a *Array[T]) Set(index int, p T) {
a.atomic.Store()(&a.array[index], p)
func (a Int32Array) Get(index int) int32 {
return a[index].Load()
}
func (a *Array[T]) Swap(index int, p T) (old T) {
return a.atomic.Swap()(&a.array[index], p)
func (a Int64Array) Get(index int) int64 {
return a[index].Load()
}
func (a *Array[T]) CompareAndSwap(index int, old, new T) (swapped bool) {
return a.atomic.CompareAndSwap()(&a.array[index], old, new)
func (a UInt32Array) Get(index int) uint32 {
return a[index].Load()
}
func (a *Int32Array) Add(index int, value int32) {
AddInt32(&a.array[index], value)
func (a UInt64Array) Get(index int) uint64 {
return a[index].Load()
}
func (a *Int64Array) Add(index int, value int64) {
AddInt64(&a.array[index], value)
func (a Array[T]) Set(index int, p *T) {
GetAtomizer[T]().Store()(&a[index], p)
}
func (a *UInt32Array) Add(index int, value uint32) {
AddUInt32(&a.array[index], value)
func (a Int32Array) Set(index int, v int32) {
a[index].Store(v)
}
func (a *UInt64Array) Add(index int, value uint64) {
AddUInt64(&a.array[index], value)
func (a Int64Array) Set(index int, v int64) {
a[index].Store(v)
}
func (a UInt32Array) Set(index int, v uint32) {
a[index].Store(v)
}
func (a UInt64Array) Set(index int, v uint64) {
a[index].Store(v)
}
func (a Array[T]) Swap(index int, p *T) (old *T) {
return GetAtomizer[T]().Swap()(&a[index], p)
}
func (a Int32Array) Swap(index int, new int32) (old int32) {
return a[index].Swap(new)
}
func (a Int64Array) Swap(index int, new int64) (old int64) {
return a[index].Swap(new)
}
func (a UInt32Array) Swap(index int, new uint32) (old uint32) {
return a[index].Swap(new)
}
func (a UInt64Array) Swap(index int, new uint64) (old uint64) {
return a[index].Swap(new)
}
func (a Array[T]) CompareAndSwap(index int, old, new *T) (swapped bool) {
return GetAtomizer[T]().CompareAndSwap()(&a[index], old, new)
}
func (a Int32Array) CompareAndSwap(index int, old, new int32) (swapped bool) {
return a[index].CompareAndSwap(old, new)
}
func (a Int64Array) CompareAndSwap(index int, old, new int64) (swapped bool) {
return a[index].CompareAndSwap(old, new)
}
func (a UInt32Array) CompareAndSwap(index int, old, new uint32) (swapped bool) {
return a[index].CompareAndSwap(old, new)
}
func (a UInt64Array) CompareAndSwap(index int, old, new uint64) (swapped bool) {
return a[index].CompareAndSwap(old, new)
}
func (a Int32Array) Add(index int, value int32) {
a[index].Add(value)
}
func (a Int64Array) Add(index int, value int64) {
a[index].Add(value)
}
func (a UInt32Array) Add(index int, value uint32) {
a[index].Add(value)
}
func (a UInt64Array) Add(index int, value uint64) {
a[index].Add(value)
}
func (a Int32Array) BitLength() int {
return len(a) * 32
}
func (a Int64Array) BitLength() int {
return len(a) * 64
}
func (a UInt32Array) BitLength() int {
return len(a) * 32
}
func (a UInt64Array) BitLength() int {
return len(a) * 64
}
func (a Int32Array) SetBit(bit int, up bool) (old bool) {
return a[bit/32].SetBit(bit%32, up)
}
func (a Int64Array) SetBit(bit int, up bool) (old bool) {
return a[bit/64].SetBit(bit%64, up)
}
func (a UInt32Array) SetBit(bit int, up bool) (old bool) {
return a[bit/32].SetBit(bit%32, up)
}
func (a UInt64Array) SetBit(bit int, up bool) (old bool) {
return a[bit/64].SetBit(bit%64, up)
}
func (a Int32Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) {
return a[bit/32].CompareAndSwapBit(bit%32, old, new)
}
func (a Int64Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) {
return a[bit/64].CompareAndSwapBit(bit%64, old, new)
}
func (a UInt32Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) {
return a[bit/32].CompareAndSwapBit(bit%32, old, new)
}
func (a UInt64Array) CompareAndSwapBit(bit int, old, new bool) (swapped bool) {
return a[bit/64].CompareAndSwapBit(bit%64, old, new)
}

21
lang/atomic/Array_test.go Normal file
View File

@ -0,0 +1,21 @@
package atomic
import (
"fmt"
"reflect"
"testing"
"github.com/tursom/GoCollections/encoding/hex"
"github.com/tursom/GoCollections/lang"
)
func TestNewInt32Array_SetBit(t *testing.T) {
fmt.Println(reflect.TypeOf(lang.Nil[atomizerImpl[int]]()).Align())
array := NewInt32Array(16)
for i := 0; i < 16; i++ {
array.SetBit(10*i, true)
}
fmt.Println(array)
fmt.Println(hex.EncodeToString(array))
}

View File

@ -14,7 +14,7 @@ import (
)
type (
Atomizer[T any] interface {
Atomic[T any] interface {
Swap(new T) (old T)
CompareAndSwap(old, new T) (swapped bool)
Load() (val T)
@ -26,91 +26,91 @@ type (
CompareAndSwapBit(bit int, old, new bool) (swapped bool)
}
Atomic[T any] interface {
Atomizer[T any] interface {
Swap() func(addr *T, new T) (old T)
CompareAndSwap() func(addr *T, old, new T) (swapped bool)
Load() func(addr *T) (val T)
Store() func(addr *T, val T)
}
atomicImpl[T any] struct {
atomizerImpl[T any] struct {
swap func(addr *T, new T) (old T)
compareAndSwap func(addr *T, old, new T) (swapped bool)
load func(addr *T) (val T)
store func(addr *T, val T)
}
atomicTyped[T any] struct {
}
)
//goland:noinspection GoUnusedGlobalVariable
var (
Int32F Atomic[int32] = &atomicImpl[int32]{
int32Atomizer = &atomizerImpl[int32]{
SwapInt32,
CompareAndSwapInt32,
LoadInt32,
StoreInt32,
}
Int64F Atomic[int64] = &atomicImpl[int64]{
int64Atomizer = &atomizerImpl[int64]{
SwapInt64,
CompareAndSwapInt64,
LoadInt64,
StoreInt64,
}
UInt32F Atomic[uint32] = &atomicImpl[uint32]{
uint32Atomizer = &atomizerImpl[uint32]{
SwapUInt32,
CompareAndSwapUInt32,
LoadUint32,
StoreUInt32,
}
UInt64F Atomic[uint64] = &atomicImpl[uint64]{
uint64Atomizer = &atomizerImpl[uint64]{
SwapUInt64,
CompareAndSwapUInt64,
LoadUint64,
StoreUInt64,
}
PointerF Atomic[unsafe.Pointer] = &atomicImpl[unsafe.Pointer]{
UnsafeSwapPointer,
UnsafeCompareAndSwapPointer,
UnsafeLoadPointer,
UnsafeStorePointer,
pointerAtomizer = &atomizerImpl[unsafe.Pointer]{
atomic.SwapPointer,
atomic.CompareAndSwapPointer,
atomic.LoadPointer,
atomic.StorePointer,
}
)
func GetAtomic[T any]() Atomic[*T] {
return atomicTyped[T]{}
func Int32Atomizer() Atomizer[int32] {
return int32Atomizer
}
func (a atomicTyped[T]) Swap() func(addr **T, new *T) (old *T) {
return SwapPointer[T]
func Int64Atomizer() Atomizer[int64] {
return int64Atomizer
}
func (a atomicTyped[T]) CompareAndSwap() func(addr **T, old *T, new *T) (swapped bool) {
return CompareAndSwapPointer[T]
func UInt32Atomizer() Atomizer[uint32] {
return uint32Atomizer
}
func (a atomicTyped[T]) Load() func(addr **T) (val *T) {
return LoadPointer[T]
func UInt64Atomizer() Atomizer[uint64] {
return uint64Atomizer
}
func (a atomicTyped[T]) Store() func(addr **T, val *T) {
return StorePointer[T]
func PointerAtomizer() Atomizer[unsafe.Pointer] {
return pointerAtomizer
}
func (a *atomicImpl[T]) Swap() func(addr *T, new T) (old T) {
func GetAtomizer[T any]() Atomizer[*T] {
return (*atomizerImpl[*T])(unsafe.Pointer(pointerAtomizer))
}
func (a *atomizerImpl[T]) Swap() func(addr *T, new T) (old T) {
return a.swap
}
func (a *atomicImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) {
func (a *atomizerImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) {
return a.compareAndSwap
}
func (a *atomicImpl[T]) Load() func(addr *T) (val T) {
func (a *atomizerImpl[T]) Load() func(addr *T) (val T) {
return a.load
}
func (a *atomicImpl[T]) Store() func(addr *T, val T) {
func (a *atomizerImpl[T]) Store() func(addr *T, val T) {
return a.store
}

View File

@ -0,0 +1,15 @@
package atomic
import (
"fmt"
"testing"
)
func TestGetAtomizer(t *testing.T) {
atomizer := GetAtomizer[int32]()
var ref *int32
var obj int32 = 1
atomizer.CompareAndSwap()(&ref, nil, &obj)
fmt.Println(*ref)
}

View File

@ -6,19 +6,17 @@
package atomic
type Bool struct {
i Int32
}
type Bool Int32
func (v *Bool) Load() (val bool) {
return v.i.Load() != 0
return (*Int32)(v).Load() != 0
}
func (v *Bool) Store(val bool) {
if val {
v.i.Store(1)
(*Int32)(v).Store(1)
} else {
v.i.Store(0)
(*Int32)(v).Store(0)
}
}
@ -27,7 +25,7 @@ func (v *Bool) Swap(new bool) (old bool) {
if new {
n = 1
}
return v.i.Swap(n) != 0
return (*Int32)(v).Swap(n) != 0
}
func (v *Bool) CompareAndSwap(old, new bool) (swapped bool) {
@ -39,5 +37,5 @@ func (v *Bool) CompareAndSwap(old, new bool) (swapped bool) {
if new {
n = 1
}
return v.i.CompareAndSwap(o, n)
return (*Int32)(v).CompareAndSwap(o, n)
}

View File

@ -42,10 +42,10 @@ func (v *Float32) CompareAndSwap(old, new float32) (swapped bool) {
}
func (v *Float32) Add(f float32) (new float32) {
old := float32(*v)
old := v.Load()
new = old + f
for !v.CompareAndSwap(old, new) {
old = float32(*v)
old = v.Load()
new = old + f
}

View File

@ -42,10 +42,10 @@ func (v *Float64) CompareAndSwap(old, new float64) (swapped bool) {
}
func (v *Float64) Add(f float64) (new float64) {
old := float64(*v)
old := v.Load()
new = old + f
for !v.CompareAndSwap(old, new) {
old = float64(*v)
old = v.Load()
new = old + f
}

View File

@ -8,12 +8,9 @@ package atomic
import (
"fmt"
"reflect"
"sync"
"testing"
"time"
"github.com/tursom/GoCollections/lang"
)
func TestInt32_SetBit(t *testing.T) {
@ -56,14 +53,3 @@ func TestInt32_CompareAndSwapBit(t *testing.T) {
time.Sleep(1 * time.Second)
fmt.Println(i.Load())
}
func TestTypeConv(t *testing.T) {
var intV lang.Int32
var i any = intV
_, ok := i.(lang.AsInt32)
fmt.Println(reflect.TypeOf(i), ok)
i = &intV
_, ok = i.(lang.AsInt32)
fmt.Println(reflect.TypeOf(i), ok)
}

View File

@ -11,21 +11,15 @@ import (
"unsafe"
"github.com/tursom/GoCollections/lang"
)
//goland:noinspection GoUnusedGlobalVariable
var (
UnsafeLoadPointer = atomic.LoadPointer
UnsafeStorePointer = atomic.StorePointer
UnsafeSwapPointer = atomic.SwapPointer
UnsafeCompareAndSwapPointer = atomic.CompareAndSwapPointer
unsafe2 "github.com/tursom/GoCollections/unsafe"
)
type (
Pointer = unsafe.Pointer
PPointer = *unsafe.Pointer
// Reference atomic type T reference
// Reference atomizer type T reference
Reference[T any] struct {
lang.BaseObject
p *T
@ -34,16 +28,16 @@ type (
// NewReference new *Reference[T] init by given reference
func NewReference[T any](reference *T) *Reference[T] {
return lang.ForceCast[Reference[T]](Pointer(&reference))
return unsafe2.ForceCast[Reference[T]](Pointer(&reference))
}
// ReferenceOf cast **T to *Reference[T]
func ReferenceOf[T any](reference **T) *Reference[T] {
return lang.ForceCast[Reference[T]](Pointer(reference))
return unsafe2.ForceCast[Reference[T]](Pointer(reference))
}
func ReferenceUintptr[T any](reference *uintptr) *Reference[T] {
return lang.ForceCast[Reference[T]](Pointer(reference))
return unsafe2.ForceCast[Reference[T]](Pointer(reference))
}
func (r *Reference[T]) AsPointer() Pointer {
@ -55,7 +49,7 @@ func (r *Reference[T]) AsPPointer() PPointer {
}
func (r *Reference[T]) AsUintptr() *TypedUintptr[T] {
return lang.ForceCast[TypedUintptr[T]](r.AsPointer())
return unsafe2.ForceCast[TypedUintptr[T]](r.AsPointer())
}
func (r *Reference[T]) pointer() **T {

View File

@ -9,7 +9,7 @@ package atomic
import (
"sync/atomic"
"github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/unsafe"
)
type (
@ -17,8 +17,8 @@ type (
TypedUintptr[T any] Uintptr
)
func (p Uintptr) Raw() uintptr {
return uintptr(p)
func (p *Uintptr) Raw() uintptr {
return uintptr(*p)
}
func (p *Uintptr) RawP() *uintptr {
@ -48,8 +48,8 @@ func (p *Uintptr) CompareAndSwap(old, new Uintptr) (swapped bool) {
return atomic.CompareAndSwapUintptr((*uintptr)(p), uintptr(old), uintptr(new))
}
func (p TypedUintptr[T]) Raw() uintptr {
return uintptr(p)
func (p *TypedUintptr[T]) Raw() uintptr {
return uintptr(*p)
}
func (p *TypedUintptr[T]) RawP() *uintptr {
@ -65,11 +65,11 @@ func (p *TypedUintptr[T]) AsPPointer() PPointer {
}
func (tp *TypedUintptr[T]) AsReference() *Reference[T] {
return lang.ForceCast[Reference[T]](Pointer(tp))
return unsafe.ForceCast[Reference[T]](Pointer(tp))
}
func (tp TypedUintptr[T]) Uintptr() Uintptr {
return Uintptr(tp)
func (tp *TypedUintptr[T]) Uintptr() Uintptr {
return Uintptr(*tp)
}
func (tp *TypedUintptr[T]) PUintptr() *Uintptr {

44
unsafe/unsafe.go Normal file
View File

@ -0,0 +1,44 @@
package unsafe
import (
"reflect"
"unsafe"
"github.com/tursom/GoCollections/lang"
)
type slice struct {
array unsafe.Pointer
len int
cap int
}
func ForceCast[T any](v unsafe.Pointer) *T {
if v == nil {
return nil
} else {
return (*T)(v)
}
}
func Sizeof[T any]() uintptr {
return unsafe.Sizeof(lang.Nil[T]())
}
// AsBytes cast any slice as []byte with same pinter, real len and real cap
func AsBytes[T any](arr []T) []byte {
sarr := *ForceCast[slice](unsafe.Pointer(&arr))
typeAlign := reflect.TypeOf(lang.Nil[T]()).Align()
asBytes := unsafe.Pointer(&slice{
array: sarr.array,
len: sarr.len * typeAlign,
cap: sarr.cap * typeAlign,
})
return *ForceCast[[]byte](asBytes)
}
// AsString cast bytes as string
func AsString(bytes []byte) string {
return *ForceCast[string](unsafe.Pointer(&bytes))
}

View File

@ -1,17 +0,0 @@
/*
* Copyright (c) 2022 tursom. All rights reserved.
* Use of this source code is governed by a GPL-3
* license that can be found in the LICENSE file.
*/
package unsafe
import (
"unsafe"
"github.com/tursom/GoCollections/lang"
)
func Sizeof[T any]() uintptr {
return unsafe.Sizeof(lang.Nil[T]())
}