1// Copyright 2014 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package atomic 6 7import ( 8 "unsafe" 9) 10 11// A Value provides an atomic load and store of a consistently typed value. 12// The zero value for a Value returns nil from Load. 13// Once Store has been called, a Value must not be copied. 14// 15// A Value must not be copied after first use. 16type Value struct { 17 noCopy noCopy 18 19 v interface{} 20} 21 22// ifaceWords is interface{} internal representation. 23type ifaceWords struct { 24 typ unsafe.Pointer 25 data unsafe.Pointer 26} 27 28// Load returns the value set by the most recent Store. 29// It returns nil if there has been no call to Store for this Value. 30func (v *Value) Load() (x interface{}) { 31 vp := (*ifaceWords)(unsafe.Pointer(v)) 32 typ := LoadPointer(&vp.typ) 33 if typ == nil || uintptr(typ) == ^uintptr(0) { 34 // First store not yet completed. 35 return nil 36 } 37 data := LoadPointer(&vp.data) 38 xp := (*ifaceWords)(unsafe.Pointer(&x)) 39 xp.typ = typ 40 xp.data = data 41 return 42} 43 44// Store sets the value of the Value to x. 45// All calls to Store for a given Value must use values of the same concrete type. 46// Store of an inconsistent type panics, as does Store(nil). 47func (v *Value) Store(x interface{}) { 48 if x == nil { 49 panic("sync/atomic: store of nil value into Value") 50 } 51 vp := (*ifaceWords)(unsafe.Pointer(v)) 52 xp := (*ifaceWords)(unsafe.Pointer(&x)) 53 for { 54 typ := LoadPointer(&vp.typ) 55 if typ == nil { 56 // Attempt to start first store. 57 // Disable preemption so that other goroutines can use 58 // active spin wait to wait for completion; and so that 59 // GC does not see the fake type accidentally. 60 runtime_procPin() 61 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { 62 runtime_procUnpin() 63 continue 64 } 65 // Complete first store. 66 StorePointer(&vp.data, xp.data) 67 StorePointer(&vp.typ, xp.typ) 68 runtime_procUnpin() 69 return 70 } 71 if uintptr(typ) == ^uintptr(0) { 72 // First store in progress. Wait. 73 // Since we disable preemption around the first store, 74 // we can wait with active spinning. 75 continue 76 } 77 // First store completed. Check type and overwrite data. 78 if typ != xp.typ { 79 panic("sync/atomic: store of inconsistently typed value into Value") 80 } 81 StorePointer(&vp.data, xp.data) 82 return 83 } 84} 85 86// Disable/enable preemption, implemented in runtime. 87func runtime_procPin() 88func runtime_procUnpin() 89 90// noCopy may be embedded into structs which must not be copied 91// after the first use. 92// 93// See https://github.com/golang/go/issues/8005#issuecomment-190753527 94// for details. 95type noCopy struct{} 96 97// Lock is a no-op used by -copylocks checker from `go vet`. 98func (*noCopy) Lock() {} 99