Value

  1. // Value 针对一个指定的类型提供 load 和 store 两个原子操作
  2. type Value struct {
  3. v interface{}
  4. }
  5. // Load returns the value set by the most recent Store.
  6. // It returns nil if there has been no call to Store for this Value.
  7. func (v *Value) Load() (x interface{}) {
  8. vp := (*ifaceWords)(unsafe.Pointer(v))
  9. typ := LoadPointer(&vp.typ)
  10. if typ == nil || uintptr(typ) == ^uintptr(0) {
  11. // First store not yet completed.
  12. return nil
  13. }
  14. data := LoadPointer(&vp.data)
  15. xp := (*ifaceWords)(unsafe.Pointer(&x))
  16. xp.typ = typ
  17. xp.data = data
  18. return
  19. }
  20. // Store sets the value of the Value to x.
  21. // All calls to Store for a given Value must use values of the same concrete type.
  22. // Store of an inconsistent type panics, as does Store(nil).
  23. func (v *Value) Store(x interface{}) {
  24. if x == nil {
  25. panic("sync/atomic: store of nil value into Value")
  26. }
  27. vp := (*ifaceWords)(unsafe.Pointer(v))
  28. xp := (*ifaceWords)(unsafe.Pointer(&x))
  29. for {
  30. typ := LoadPointer(&vp.typ)
  31. if typ == nil {
  32. // Attempt to start first store.
  33. // Disable preemption so that other goroutines can use
  34. // active spin wait to wait for completion; and so that
  35. // GC does not see the fake type accidentally.
  36. runtime_procPin()
  37. if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
  38. runtime_procUnpin()
  39. continue
  40. }
  41. // Complete first store.
  42. StorePointer(&vp.data, xp.data)
  43. StorePointer(&vp.typ, xp.typ)
  44. runtime_procUnpin()
  45. return
  46. }
  47. if uintptr(typ) == ^uintptr(0) {
  48. // First store in progress. Wait.
  49. // Since we disable preemption around the first store,
  50. // we can wait with active spinning.
  51. continue
  52. }
  53. // First store completed. Check type and overwrite data.
  54. if typ != xp.typ {
  55. panic("sync/atomic: store of inconsistently typed value into Value")
  56. }
  57. StorePointer(&vp.data, xp.data)
  58. return
  59. }
  60. }