GoCollections/lang/atomic/Reference.go
2023-04-16 14:57:20 +08:00

94 lines
2.1 KiB
Go

/*
* 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 atomic
import (
"sync/atomic"
"unsafe"
"github.com/tursom/GoCollections/lang"
unsafe2 "github.com/tursom/GoCollections/unsafe"
)
type (
Pointer = unsafe.Pointer
PPointer = *unsafe.Pointer
// Reference atomizer type T reference
Reference[T any] struct {
lang.BaseObject
p *T
}
)
// NewReference new *Reference[T] init by given reference
func NewReference[T any](reference *T) *Reference[T] {
return &Reference[T]{p: reference}
}
// ReferenceOf cast **T to *Reference[T]
func ReferenceOf[T any](reference **T) *Reference[T] {
return unsafe2.ForceCast[Reference[T]](Pointer(reference))
}
func ReferenceUintptr[T any](reference *uintptr) *Reference[T] {
return unsafe2.ForceCast[Reference[T]](Pointer(reference))
}
func (r *Reference[T]) AsPointer() Pointer {
return Pointer(r)
}
func (r *Reference[T]) AsPPointer() PPointer {
return PPointer(r.AsPointer())
}
func (r *Reference[T]) AsUintptr() *TypedUintptr[T] {
return unsafe2.ForceCast[TypedUintptr[T]](r.AsPointer())
}
func (r *Reference[T]) pointer() **T {
return &r.p
}
func (r *Reference[T]) Load() (val *T) {
return LoadPointer(r.pointer())
}
func (r *Reference[T]) Store(val *T) {
StorePointer(r.pointer(), val)
}
func (r *Reference[T]) Swap(new *T) (old *T) {
return SwapPointer(r.pointer(), new)
}
func (r *Reference[T]) CompareAndSwap(old, new *T) (swapped bool) {
return CompareAndSwapPointer(r.pointer(), old, new)
}
func AsPPointer[T any](p **T) PPointer {
return PPointer(Pointer(p))
}
func LoadPointer[T any](addr **T) (val *T) {
return (*T)(atomic.LoadPointer(AsPPointer(addr)))
}
func StorePointer[T any](addr **T, val *T) {
atomic.StorePointer(AsPPointer(addr), Pointer(val))
}
func SwapPointer[T any](addr **T, new *T) (old *T) {
return (*T)(atomic.SwapPointer(AsPPointer(addr), Pointer(new)))
}
func CompareAndSwapPointer[T any](addr **T, old, new *T) (swapped bool) {
return atomic.CompareAndSwapPointer(AsPPointer(addr), Pointer(old), Pointer(new))
}