1// Copyright 2018 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_test 6 7import ( 8 "sync" 9 "sync/atomic" 10 "time" 11) 12 13func loadConfig() map[string]string { 14 return make(map[string]string) 15} 16 17func requests() chan int { 18 return make(chan int) 19} 20 21// The following example shows how to use Value for periodic program config updates 22// and propagation of the changes to worker goroutines. 23func ExampleValue_config() { 24 var config atomic.Value // holds current server configuration 25 // Create initial config value and store into config. 26 config.Store(loadConfig()) 27 go func() { 28 // Reload config every 10 seconds 29 // and update config value with the new version. 30 for { 31 time.Sleep(10 * time.Second) 32 config.Store(loadConfig()) 33 } 34 }() 35 // Create worker goroutines that handle incoming requests 36 // using the latest config value. 37 for i := 0; i < 10; i++ { 38 go func() { 39 for r := range requests() { 40 c := config.Load() 41 // Handle request r using config c. 42 _, _ = r, c 43 } 44 }() 45 } 46} 47 48// The following example shows how to maintain a scalable frequently read, 49// but infrequently updated data structure using copy-on-write idiom. 50func ExampleValue_readMostly() { 51 type Map map[string]string 52 var m atomic.Value 53 m.Store(make(Map)) 54 var mu sync.Mutex // used only by writers 55 // read function can be used to read the data without further synchronization 56 read := func(key string) (val string) { 57 m1 := m.Load().(Map) 58 return m1[key] 59 } 60 // insert function can be used to update the data without further synchronization 61 insert := func(key, val string) { 62 mu.Lock() // synchronize with other potential writers 63 defer mu.Unlock() 64 m1 := m.Load().(Map) // load current value of the data structure 65 m2 := make(Map) // create a new value 66 for k, v := range m1 { 67 m2[k] = v // copy all data from the current object to the new one 68 } 69 m2[key] = val // do the update that we need 70 m.Store(m2) // atomically replace the current object with the new one 71 // At this point all new readers start working with the new version. 72 // The old version will be garbage collected once the existing readers 73 // (if any) are done with it. 74 } 75 _, _ = read, insert 76} 77