dd931d9b48
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
// 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
|
|
}
|