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 5 package atomic_test 6 7 import ( 8 "sync" 9 "sync/atomic" 10 "time" 11 ) 12 13 func loadConfig() map[string]string { 14 return make(map[string]string) 15 } 16 17 func 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. 23 func 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. 50 func 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