Source file src/sync/atomic/example_test.go

     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  

View as plain text