|  | // Copyright 2018 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_test | 
|  |  | 
|  | import ( | 
|  | "sync" | 
|  | "sync/atomic" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | func loadConfig() map[string]string { | 
|  | return make(map[string]string) | 
|  | } | 
|  |  | 
|  | func requests() chan int { | 
|  | return make(chan int) | 
|  | } | 
|  |  | 
|  | // The following example shows how to use Value for periodic program config updates | 
|  | // and propagation of the changes to worker goroutines. | 
|  | func ExampleValue_config() { | 
|  | var config atomic.Value // holds current server configuration | 
|  | // Create initial config value and store into config. | 
|  | config.Store(loadConfig()) | 
|  | go func() { | 
|  | // Reload config every 10 seconds | 
|  | // and update config value with the new version. | 
|  | for { | 
|  | time.Sleep(10 * time.Second) | 
|  | config.Store(loadConfig()) | 
|  | } | 
|  | }() | 
|  | // Create worker goroutines that handle incoming requests | 
|  | // using the latest config value. | 
|  | for i := 0; i < 10; i++ { | 
|  | go func() { | 
|  | for r := range requests() { | 
|  | c := config.Load() | 
|  | // Handle request r using config c. | 
|  | _, _ = r, c | 
|  | } | 
|  | }() | 
|  | } | 
|  | } | 
|  |  | 
|  | // The following example shows how to maintain a scalable frequently read, | 
|  | // but infrequently updated data structure using copy-on-write idiom. | 
|  | func ExampleValue_readMostly() { | 
|  | type Map map[string]string | 
|  | var m atomic.Value | 
|  | m.Store(make(Map)) | 
|  | var mu sync.Mutex // used only by writers | 
|  | // read function can be used to read the data without further synchronization | 
|  | read := func(key string) (val string) { | 
|  | m1 := m.Load().(Map) | 
|  | return m1[key] | 
|  | } | 
|  | // insert function can be used to update the data without further synchronization | 
|  | insert := func(key, val string) { | 
|  | mu.Lock() // synchronize with other potential writers | 
|  | defer mu.Unlock() | 
|  | m1 := m.Load().(Map) // load current value of the data structure | 
|  | m2 := make(Map)      // create a new value | 
|  | for k, v := range m1 { | 
|  | m2[k] = v // copy all data from the current object to the new one | 
|  | } | 
|  | m2[key] = val // do the update that we need | 
|  | m.Store(m2)   // atomically replace the current object with the new one | 
|  | // At this point all new readers start working with the new version. | 
|  | // The old version will be garbage collected once the existing readers | 
|  | // (if any) are done with it. | 
|  | } | 
|  | _, _ = read, insert | 
|  | } |