gitee.com/go-spring2/spring-base@v1.1.3/atomic/pointer_test.go (about)

     1  /*
     2   * Copyright 2012-2019 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package atomic_test
    18  
    19  import (
    20  	"errors"
    21  	"testing"
    22  	"unsafe"
    23  
    24  	"gitee.com/go-spring2/spring-base/assert"
    25  	"gitee.com/go-spring2/spring-base/atomic"
    26  	"gitee.com/go-spring2/spring-base/json"
    27  )
    28  
    29  type properties struct {
    30  	Data int
    31  }
    32  
    33  func BenchmarkPointer(b *testing.B) {
    34  
    35  	// Pointer and Value have almost same access performance.
    36  	// BenchmarkPointer/value-8	    47710915   25.72 ns/op
    37  	// BenchmarkPointer/pointer-8   44618223   25.78 ns/op
    38  
    39  	b.Run("pointer", func(b *testing.B) {
    40  		var p atomic.Pointer
    41  		for i := 0; i < b.N; i++ {
    42  			p.Store(unsafe.Pointer(&properties{Data: 1}))
    43  			prop := (*properties)(p.Load())
    44  			if prop.Data != 1 {
    45  				b.Fatal(errors.New("prop data should be 1"))
    46  			}
    47  		}
    48  	})
    49  
    50  	b.Run("value", func(b *testing.B) {
    51  		var p atomic.Value
    52  		for i := 0; i < b.N; i++ {
    53  			p.Store(&properties{Data: 2})
    54  			prop := p.Load().(*properties)
    55  			if prop.Data != 2 {
    56  				b.Fatal(errors.New("prop data should be 2"))
    57  			}
    58  		}
    59  	})
    60  }
    61  
    62  func TestPointer(t *testing.T) {
    63  
    64  	// atomic.Pointer and unsafe.Pointer occupy the same space
    65  	assert.Equal(t, unsafe.Sizeof(atomic.Pointer{}), uintptr(8+8))
    66  
    67  	var p atomic.Pointer
    68  	assert.Equal(t, p.Load(), unsafe.Pointer(nil))
    69  
    70  	s1 := &properties{Data: 1}
    71  	p.Store(unsafe.Pointer(s1))
    72  	assert.Equal(t, p.Load(), unsafe.Pointer(s1))
    73  
    74  	s2 := &properties{Data: 2}
    75  	old := p.Swap(unsafe.Pointer(s2))
    76  	assert.Equal(t, old, unsafe.Pointer(s1))
    77  	assert.Equal(t, p.Load(), unsafe.Pointer(s2))
    78  
    79  	s3 := &properties{Data: 3}
    80  	swapped := p.CompareAndSwap(unsafe.Pointer(s2), unsafe.Pointer(s3))
    81  	assert.True(t, swapped)
    82  	assert.Equal(t, p.Load(), unsafe.Pointer(s3))
    83  
    84  	swapped = p.CompareAndSwap(unsafe.Pointer(s2), unsafe.Pointer(s3))
    85  	assert.False(t, swapped)
    86  	assert.Equal(t, p.Load(), unsafe.Pointer(s3))
    87  
    88  	p.SetMarshalJSON(func(pointer unsafe.Pointer) ([]byte, error) {
    89  		s := (*properties)(pointer)
    90  		return json.Marshal(s)
    91  	})
    92  
    93  	bytes, _ := json.Marshal(&p)
    94  	assert.Equal(t, string(bytes), `{"Data":3}`)
    95  }