fix issue in Add function for gtype.Float32/Float64

This commit is contained in:
John
2019-04-15 22:55:12 +08:00
parent 8a32a8271c
commit 2f7d4cd80d
16 changed files with 209 additions and 118 deletions

View File

@ -44,6 +44,7 @@
1. 添加sqlite数据库的单元测试用例
1. gredis增加cluster支持
1. gset.Add/Remove/Contains方法增加批量操作支持
1. gmlock增加手动清理机制当内存锁不再使用时由调用端决定是否清理内存锁
# DONE
1. gconv完善针对不同类型的判断例如尽量减少sprintf("%v", xxx)来执行string类型的转换

View File

@ -11,35 +11,39 @@ import (
)
type Bool struct {
val int32
value int32
}
// NewBool returns a concurrent-safe object for bool type,
// with given initial value <value>.
func NewBool(value...bool) *Bool {
t := &Bool{}
if len(value) > 0 {
if value[0] {
t.val = 1
t.value = 1
} else {
t.val = 0
t.value = 0
}
}
return t
}
// Clone clones and returns a new concurrent-safe object for bool type.
func (t *Bool) Clone() *Bool {
return NewBool(t.Val())
}
// 并发安全设置变量值,返回之前的旧值
// Set atomically stores value into t.valueue and returns the previous t.value value.
func (t *Bool) Set(value bool) (old bool) {
if value {
old = atomic.SwapInt32(&t.val, 1) == 1
old = atomic.SwapInt32(&t.value, 1) == 1
} else {
old = atomic.SwapInt32(&t.val, 0) == 1
old = atomic.SwapInt32(&t.value, 0) == 1
}
return
}
// Val atomically loads t.valueue.
func (t *Bool) Val() bool {
return atomic.LoadInt32(&t.val) > 0
return atomic.LoadInt32(&t.value) > 0
}

View File

@ -11,29 +11,36 @@ import (
)
type Byte struct {
val int32
value int32
}
// NewByte returns a concurrent-safe object for byte type,
// with given initial value <value>.
func NewByte(value...byte) *Byte {
if len(value) > 0 {
return &Byte{val : int32(value[0])}
return &Byte{
value : int32(value[0]),
}
}
return &Byte{}
}
// Clone clones and returns a new concurrent-safe object for byte type.
func (t *Byte) Clone() *Byte {
return NewByte(t.Val())
}
// 并发安全设置变量值,返回之前的旧值
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Byte) Set(value byte) (old byte) {
return byte(atomic.SwapInt32(&t.val, int32(value)))
return byte(atomic.SwapInt32(&t.value, int32(value)))
}
// Val atomically loads t.value.
func (t *Byte) Val() byte {
return byte(atomic.LoadInt32(&t.val))
return byte(atomic.LoadInt32(&t.value))
}
func (t *Byte) Add(delta int) byte {
return byte(atomic.AddInt32(&t.val, int32(delta)))
// Add atomically adds delta to t.value and returns the new value.
func (t *Byte) Add(delta int) (new byte) {
return byte(atomic.AddInt32(&t.value, int32(delta)))
}

View File

@ -9,29 +9,35 @@ package gtype
import "sync/atomic"
type Bytes struct {
val atomic.Value
value atomic.Value
}
// NewBytes returns a concurrent-safe object for []byte type,
// with given initial value <value>.
func NewBytes(value...[]byte) *Bytes {
t := &Bytes{}
if len(value) > 0 {
t.val.Store(value[0])
t.value.Store(value[0])
}
return t
}
// Clone clones and returns a new concurrent-safe object for []byte type.
func (t *Bytes) Clone() *Bytes {
return NewBytes(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
// Note: The parameter <value> cannot be nil.
func (t *Bytes) Set(value []byte) (old []byte) {
old = t.Val()
t.val.Store(value)
t.value.Store(value)
return
}
// Val atomically loads t.value.
func (t *Bytes) Val() []byte {
if s := t.val.Load(); s != nil {
if s := t.value.Load(); s != nil {
return s.([]byte)
}
return nil

View File

@ -7,47 +7,53 @@
package gtype
import (
"sync/atomic"
"github.com/gogf/gf/g/encoding/gbinary"
"math"
"sync/atomic"
"unsafe"
)
type Float32 struct {
val uint32
value uint32
}
// NewFloat32 returns a concurrent-safe object for float32 type,
// with given initial value <value>.
func NewFloat32(value...float32) *Float32 {
if len(value) > 0 {
return &Float32{ val : float32ToUint32InBits(value[0]) }
return &Float32{
value : math.Float32bits(value[0]),
}
}
return &Float32{}
}
// Clone clones and returns a new concurrent-safe object for float32 type.
func (t *Float32) Clone() *Float32 {
return NewFloat32(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Float32) Set(value float32) (old float32) {
return uint32ToFloat32InBits(atomic.SwapUint32(&t.val, float32ToUint32InBits(value)))
return math.Float32frombits(atomic.SwapUint32(&t.value, math.Float32bits(value)))
}
// Val atomically loads t.value.
func (t *Float32) Val() float32 {
return uint32ToFloat32InBits(atomic.LoadUint32(&t.val))
return math.Float32frombits(atomic.LoadUint32(&t.value))
}
func (t *Float32) Add(delta float32) float32 {
return uint32ToFloat32InBits(atomic.AddUint32(&t.val, float32ToUint32InBits(delta)))
}
// 通过二进制的方式将float32转换为uint32(都是32bits)
func float32ToUint32InBits(value float32) uint32 {
b := gbinary.Encode(value)
i := gbinary.DecodeToUint32(b)
return i
}
// 通过二进制的方式将uint32转换为float32(都是32bits)
func uint32ToFloat32InBits(value uint32) float32 {
b := gbinary.Encode(value)
f := gbinary.DecodeToFloat32(b)
return f
// Add atomically adds delta to t.value and returns the new value.
func (t *Float32) Add(delta float32) (new float32) {
for {
old := math.Float32frombits(t.value)
new = old + delta
if atomic.CompareAndSwapUint32(
(*uint32)(unsafe.Pointer(&t.value)),
math.Float32bits(old),
math.Float32bits(new),
) {
break
}
}
return
}

View File

@ -7,47 +7,53 @@
package gtype
import (
"sync/atomic"
"github.com/gogf/gf/g/encoding/gbinary"
"math"
"sync/atomic"
"unsafe"
)
type Float64 struct {
val uint64
value uint64
}
// NewFloat64 returns a concurrent-safe object for float64 type,
// with given initial value <value>.
func NewFloat64(value...float64) *Float64 {
if len(value) > 0 {
return &Float64{ val : float64ToUint64InBits(value[0]) }
return &Float64{
value : math.Float64bits(value[0]),
}
}
return &Float64{}
}
// Clone clones and returns a new concurrent-safe object for float64 type.
func (t *Float64) Clone() *Float64 {
return NewFloat64(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Float64) Set(value float64) (old float64) {
return uint64ToFloat64InBits(atomic.SwapUint64(&t.val, float64ToUint64InBits(value)))
return math.Float64frombits(atomic.SwapUint64(&t.value, math.Float64bits(value)))
}
// Val atomically loads t.value.
func (t *Float64) Val() float64 {
return uint64ToFloat64InBits(atomic.LoadUint64(&t.val))
return math.Float64frombits(atomic.LoadUint64(&t.value))
}
func (t *Float64) Add(delta float64) float64 {
return uint64ToFloat64InBits(atomic.AddUint64(&t.val, float64ToUint64InBits(delta)))
// Add atomically adds delta to t.value and returns the new value.
func (t *Float64) Add(delta float64) (new float64) {
for {
old := math.Float64frombits(t.value)
new = old + delta
if atomic.CompareAndSwapUint64(
(*uint64)(unsafe.Pointer(&t.value)),
math.Float64bits(old),
math.Float64bits(new),
) {
break
}
}
return
}
// 通过二进制的方式将float64转换为uint64(都是64bits)
func float64ToUint64InBits(value float64) uint64 {
b := gbinary.Encode(value)
i := gbinary.DecodeToUint64(b)
return i
}
// 通过二进制的方式将uint64转换为float64(都是64bits)
func uint64ToFloat64InBits(value uint64) float64 {
b := gbinary.Encode(value)
f := gbinary.DecodeToFloat64(b)
return f
}

View File

@ -4,11 +4,12 @@
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
// Package gtype provides kinds of high performance, concurrent-safe/unsafe basic variable types.
// Package gtype provides kinds of high performance and concurrent-safe basic variable types.
package gtype
type Type = Interface
// See NewInterface.
func New(value ... interface{}) *Type {
return NewInterface(value...)
}

View File

@ -11,30 +11,36 @@ import (
)
type Int struct {
val int64
value int64
}
// NewInt returns a concurrent-safe object for int type,
// with given initial value <value>.
func NewInt(value...int) *Int {
if len(value) > 0 {
return &Int{val:int64(value[0])}
return &Int{
value : int64(value[0]),
}
}
return &Int{}
}
// Clone clones and returns a new concurrent-safe object for int type.
func (t *Int) Clone() *Int {
return NewInt(t.Val())
}
// 并发安全设置变量值,返回之前的旧值
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Int) Set(value int) (old int) {
return int(atomic.SwapInt64(&t.val, int64(value)))
return int(atomic.SwapInt64(&t.value, int64(value)))
}
// Val atomically loads t.value.
func (t *Int) Val() int {
return int(atomic.LoadInt64(&t.val))
return int(atomic.LoadInt64(&t.value))
}
// 数值增加delta并返回**新**的数值
func (t *Int) Add(delta int) int {
return int(atomic.AddInt64(&t.val, int64(delta)))
// Add atomically adds delta to t.value and returns the new value.
func (t *Int) Add(delta int) (new int) {
return int(atomic.AddInt64(&t.value, int64(delta)))
}

View File

@ -11,28 +11,36 @@ import (
)
type Int32 struct {
val int32
value int32
}
// NewInt32 returns a concurrent-safe object for int32 type,
// with given initial value <value>.
func NewInt32(value...int32) *Int32 {
if len(value) > 0 {
return &Int32{val: value[0]}
return &Int32{
value : value[0],
}
}
return &Int32{}
}
// Clone clones and returns a new concurrent-safe object for int32 type.
func (t *Int32) Clone() *Int32 {
return NewInt32(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Int32) Set(value int32) (old int32) {
return atomic.SwapInt32(&t.val, value)
return atomic.SwapInt32(&t.value, value)
}
// Val atomically loads t.value.
func (t *Int32) Val() int32 {
return atomic.LoadInt32(&t.val)
return atomic.LoadInt32(&t.value)
}
func (t *Int32) Add(delta int32) int32 {
return atomic.AddInt32(&t.val, delta)
// Add atomically adds delta to t.value and returns the new value.
func (t *Int32) Add(delta int32) (new int32) {
return atomic.AddInt32(&t.value, delta)
}

View File

@ -11,28 +11,36 @@ import (
)
type Int64 struct {
val int64
value int64
}
// NewInt64 returns a concurrent-safe object for int64 type,
// with given initial value <value>.
func NewInt64(value...int64) *Int64 {
if len(value) > 0 {
return &Int64{val:value[0]}
return &Int64{
value : value[0],
}
}
return &Int64{}
}
// Clone clones and returns a new concurrent-safe object for int64 type.
func (t *Int64) Clone() *Int64 {
return NewInt64(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Int64) Set(value int64) (old int64) {
return atomic.SwapInt64(&t.val, value)
return atomic.SwapInt64(&t.value, value)
}
// Val atomically loads t.value.
func (t *Int64) Val() int64 {
return atomic.LoadInt64(&t.val)
return atomic.LoadInt64(&t.value)
}
// Add atomically adds delta to t.value and returns the new value.
func (t *Int64) Add(delta int64) int64 {
return atomic.AddInt64(&t.val, delta)
return atomic.AddInt64(&t.value, delta)
}

View File

@ -10,32 +10,34 @@ import (
"sync/atomic"
)
// 比较通用的并发安全数据类型
type Interface struct {
val atomic.Value
value atomic.Value
}
// NewInterface returns a concurrent-safe object for interface{} type,
// with given initial value <value>.
func NewInterface(value...interface{}) *Interface {
t := &Interface{}
if len(value) > 0 && value[0] != nil {
t.val.Store(value[0])
t.value.Store(value[0])
}
return t
}
// Clone clones and returns a new concurrent-safe object for interface{} type.
func (t *Interface) Clone() *Interface {
return NewInterface(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
// Note: The parameter <value> cannot be nil.
func (t *Interface) Set(value interface{}) (old interface{}) {
if value == nil {
return
}
old = t.Val()
t.val.Store(value)
t.value.Store(value)
return
}
// Val atomically loads t.value.
func (t *Interface) Val() interface{} {
return t.val.Load()
return t.value.Load()
}

View File

@ -11,29 +11,34 @@ import (
)
type String struct {
val atomic.Value
value atomic.Value
}
// NewString returns a concurrent-safe object for string type,
// with given initial value <value>.
func NewString(value...string) *String {
t := &String{}
if len(value) > 0 {
t.val.Store(value[0])
t.value.Store(value[0])
}
return t
}
// Clone clones and returns a new concurrent-safe object for string type.
func (t *String) Clone() *String {
return NewString(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *String) Set(value string) (old string) {
old = t.Val()
t.val.Store(value)
t.value.Store(value)
return
}
// Val atomically loads t.value.
func (t *String) Val() string {
s := t.val.Load()
s := t.value.Load()
if s != nil {
return s.(string)
}

View File

@ -11,28 +11,36 @@ import (
)
type Uint struct {
val uint64
value uint64
}
// NewUint returns a concurrent-safe object for uint type,
// with given initial value <value>.
func NewUint(value...uint) *Uint {
if len(value) > 0 {
return &Uint{val:uint64(value[0])}
return &Uint{
value : uint64(value[0]),
}
}
return &Uint{}
}
// Clone clones and returns a new concurrent-safe object for uint type.
func (t *Uint) Clone() *Uint {
return NewUint(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Uint) Set(value uint) (old uint) {
return uint(atomic.SwapUint64(&t.val, uint64(value)))
return uint(atomic.SwapUint64(&t.value, uint64(value)))
}
// Val atomically loads t.value.
func (t *Uint) Val() uint {
return uint(atomic.LoadUint64(&t.val))
return uint(atomic.LoadUint64(&t.value))
}
func (t *Uint) Add(delta uint) int {
return int(atomic.AddUint64(&t.val, uint64(delta)))
// Add atomically adds delta to t.value and returns the new value.
func (t *Uint) Add(delta uint) (new uint) {
return uint(atomic.AddUint64(&t.value, uint64(delta)))
}

View File

@ -11,28 +11,36 @@ import (
)
type Uint32 struct {
val uint32
value uint32
}
// NewUint32 returns a concurrent-safe object for uint32 type,
// with given initial value <value>.
func NewUint32(value...uint32) *Uint32 {
if len(value) > 0 {
return &Uint32{val:value[0]}
return &Uint32{
value : value[0],
}
}
return &Uint32{}
}
// Clone clones and returns a new concurrent-safe object for uint32 type.
func (t *Uint32) Clone() *Uint32 {
return NewUint32(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Uint32) Set(value uint32) (old uint32) {
return atomic.SwapUint32(&t.val, value)
return atomic.SwapUint32(&t.value, value)
}
// Val atomically loads t.value.
func (t *Uint32) Val() uint32 {
return atomic.LoadUint32(&t.val)
return atomic.LoadUint32(&t.value)
}
func (t *Uint32) Add(delta uint32) uint32 {
return atomic.AddUint32(&t.val, delta)
// Add atomically adds delta to t.value and returns the new value.
func (t *Uint32) Add(delta uint32) (new uint32) {
return atomic.AddUint32(&t.value, delta)
}

View File

@ -11,28 +11,36 @@ import (
)
type Uint64 struct {
val uint64
value uint64
}
// NewUint64 returns a concurrent-safe object for uint64 type,
// with given initial value <value>.
func NewUint64(value...uint64) *Uint64 {
if len(value) > 0 {
return &Uint64{val:value[0]}
return &Uint64{
value : value[0],
}
}
return &Uint64{}
}
// Clone clones and returns a new concurrent-safe object for uint64 type.
func (t *Uint64) Clone() *Uint64 {
return NewUint64(t.Val())
}
// Set atomically stores value into t.value and returns the previous t.value value.
func (t *Uint64) Set(value uint64) (old uint64) {
return atomic.SwapUint64(&t.val, value)
return atomic.SwapUint64(&t.value, value)
}
// Val atomically loads t.value.
func (t *Uint64) Val() uint64 {
return atomic.LoadUint64(&t.val)
return atomic.LoadUint64(&t.value)
}
func (t *Uint64) Add(delta uint64) uint64 {
return atomic.AddUint64(&t.val, delta)
// Add atomically adds delta to t.value and returns the new value.
func (t *Uint64) Add(delta uint64) (new uint64) {
return atomic.AddUint64(&t.value, delta)
}

View File

@ -2,14 +2,21 @@ package main
import (
"fmt"
"github.com/gogf/gf/g/util/grand"
"github.com/gogf/gf/g/container/gtype"
"github.com/gogf/gf/g/test/gtest"
)
func main() {
for {
fmt.Println(grand.Intn(100))
}
var add float32
add = 3.1415926
myF32 := gtype.NewFloat32(add)
myAdd := myF32.Add(float32(6.2951413))
add += float32(6.2951413)
fmt.Println(myF32.Val())
gtest.AssertEQ(myAdd, add)
}