|  | // Copyright 2014 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package atomic | 
|  |  | 
|  | import ( | 
|  | "unsafe" | 
|  | ) | 
|  |  | 
|  | // A Value provides an atomic load and store of a consistently typed value. | 
|  | // The zero value for a Value returns nil from Load. | 
|  | // Once Store has been called, a Value must not be copied. | 
|  | // | 
|  | // A Value must not be copied after first use. | 
|  | type Value struct { | 
|  | v interface{} | 
|  | } | 
|  |  | 
|  | // ifaceWords is interface{} internal representation. | 
|  | type ifaceWords struct { | 
|  | typ  unsafe.Pointer | 
|  | data unsafe.Pointer | 
|  | } | 
|  |  | 
|  | // Load returns the value set by the most recent Store. | 
|  | // It returns nil if there has been no call to Store for this Value. | 
|  | func (v *Value) Load() (x interface{}) { | 
|  | vp := (*ifaceWords)(unsafe.Pointer(v)) | 
|  | typ := LoadPointer(&vp.typ) | 
|  | if typ == nil || uintptr(typ) == ^uintptr(0) { | 
|  | // First store not yet completed. | 
|  | return nil | 
|  | } | 
|  | data := LoadPointer(&vp.data) | 
|  | xp := (*ifaceWords)(unsafe.Pointer(&x)) | 
|  | xp.typ = typ | 
|  | xp.data = data | 
|  | return | 
|  | } | 
|  |  | 
|  | // Store sets the value of the Value to x. | 
|  | // All calls to Store for a given Value must use values of the same concrete type. | 
|  | // Store of an inconsistent type panics, as does Store(nil). | 
|  | func (v *Value) Store(x interface{}) { | 
|  | if x == nil { | 
|  | panic("sync/atomic: store of nil value into Value") | 
|  | } | 
|  | vp := (*ifaceWords)(unsafe.Pointer(v)) | 
|  | xp := (*ifaceWords)(unsafe.Pointer(&x)) | 
|  | for { | 
|  | typ := LoadPointer(&vp.typ) | 
|  | if typ == nil { | 
|  | // Attempt to start first store. | 
|  | // Disable preemption so that other goroutines can use | 
|  | // active spin wait to wait for completion; and so that | 
|  | // GC does not see the fake type accidentally. | 
|  | runtime_procPin() | 
|  | if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { | 
|  | runtime_procUnpin() | 
|  | continue | 
|  | } | 
|  | // Complete first store. | 
|  | StorePointer(&vp.data, xp.data) | 
|  | StorePointer(&vp.typ, xp.typ) | 
|  | runtime_procUnpin() | 
|  | return | 
|  | } | 
|  | if uintptr(typ) == ^uintptr(0) { | 
|  | // First store in progress. Wait. | 
|  | // Since we disable preemption around the first store, | 
|  | // we can wait with active spinning. | 
|  | continue | 
|  | } | 
|  | // First store completed. Check type and overwrite data. | 
|  | if typ != xp.typ { | 
|  | panic("sync/atomic: store of inconsistently typed value into Value") | 
|  | } | 
|  | StorePointer(&vp.data, xp.data) | 
|  | return | 
|  | } | 
|  | } | 
|  |  | 
|  | // Disable/enable preemption, implemented in runtime. | 
|  | func runtime_procPin() | 
|  | func runtime_procUnpin() |