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