| // run |
| |
| // Copyright 2022 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 main |
| |
| import ( |
| "sync/atomic" |
| "unsafe" |
| ) |
| |
| var one interface{} = 1 |
| |
| type eface struct { |
| typ unsafe.Pointer |
| data unsafe.Pointer |
| } |
| |
| func f(c chan struct{}) { |
| var x atomic.Value |
| |
| go func() { |
| x.Swap(one) // writing using the old marker |
| }() |
| for i := 0; i < 100000; i++ { |
| v := x.Load() // reading using the new marker |
| |
| p := (*eface)(unsafe.Pointer(&v)).typ |
| if uintptr(p) == ^uintptr(0) { |
| // We read the old marker, which the new reader |
| // doesn't know is a case where it should retry |
| // instead of returning it. |
| panic("bad typ field") |
| } |
| } |
| c <- struct{}{} |
| } |
| |
| func main() { |
| c := make(chan struct{}, 10) |
| for i := 0; i < 10; i++ { |
| go f(c) |
| } |
| for i := 0; i < 10; i++ { |
| <-c |
| } |
| } |