func NewStringMap(name string) *StringMap {
	v := &StringMap{values: make(map[string]string)}
	publish(name, v)
	return v
}
NewStringMap returns a new StringMap
package stats
import (
	"bytes"
	"expvar"
	"flag"
	"fmt"
	"strconv"
	"sync"
	"time"
	"xbase/sync2"
)
var emitStats = flag.Bool("emit_stats", false, "true iff we should emit stats to push-based monitoring/stats backends")
var statsEmitPeriod = flag.Duration("stats_emit_period", time.Duration(60*time.Second), "Interval between emitting stats to all registered backends")
var statsBackend = flag.String("stats_backend", "influxdb", "The name of the registered push-based monitoring/stats backend to use")
type NewVarHook func(name string, v expvar.Var)
type varGroup struct {
	sync.Mutex
	vars       map[string]expvar.Var
	newVarHook NewVarHook
}
func (vg *varGroup) register(nvh NewVarHook) {
	vg.Lock()
	defer vg.Unlock()
	if vg.newVarHook != nil {
		panic("You've already registered a function")
	}
	if nvh == nil {
		panic("nil not allowed")
	}
	vg.newVarHook = nvh
	for k, v := range vg.vars {
		nvh(k, v)
	}
	vg.vars = nil
}
func (vg *varGroup) publish(name string, v expvar.Var) {
	vg.Lock()
	defer vg.Unlock()
	if expvar.Get(name) == nil {
		expvar.Publish(name, v)
		if vg.newVarHook != nil {
			vg.newVarHook(name, v)
		} else {
			vg.vars[name] = v
		}
	}
}
var defaultVarGroup = varGroup{vars: make(map[string]expvar.Var)}
func Register(nvh NewVarHook) {
	defaultVarGroup.register(nvh)
}
func Publish(name string, v expvar.Var) {
	publish(name, v)
}
func publish(name string, v expvar.Var) {
	defaultVarGroup.publish(name, v)
}
type PushBackend interface {
	PushAll() error
}
var pushBackends = make(map[string]PushBackend)
var once sync.Once
func RegisterPushBackend(name string, backend PushBackend) {
	if _, ok := pushBackends[name]; ok {
	}
	pushBackends[name] = backend
	if *emitStats {
		once.Do(func() {
			go emitToBackend(statsEmitPeriod)
		})
	}
}
func emitToBackend(emitPeriod *time.Duration) {
	ticker := time.NewTicker(*emitPeriod)
	defer ticker.Stop()
	for range ticker.C {
		backend, ok := pushBackends[*statsBackend]
		if !ok {
			return
		}
		err := backend.PushAll()
		if err != nil {
		}
	}
}
type Float struct {
	mu sync.Mutex
	f  float64
}
func NewFloat(name string) *Float {
	v := new(Float)
	publish(name, v)
	return v
}
func (v *Float) Add(delta float64) {
	v.mu.Lock()
	v.f += delta
	v.mu.Unlock()
}
func (v *Float) Set(value float64) {
	v.mu.Lock()
	v.f = value
	v.mu.Unlock()
}
func (v *Float) Get() float64 {
	v.mu.Lock()
	f := v.f
	v.mu.Unlock()
	return f
}
func (v *Float) String() string {
	return strconv.FormatFloat(v.Get(), 'g', -1, 64)
}
type FloatFunc func() float64
func (f FloatFunc) String() string {
	return strconv.FormatFloat(f(), 'g', -1, 64)
}
type Int struct {
	i sync2.AtomicInt64
}
func NewInt(name string) *Int {
	v := new(Int)
	if name != "" {
		publish(name, v)
	}
	return v
}
func (v *Int) Add(delta int64) {
	v.i.Add(delta)
}
func (v *Int) Set(value int64) {
	v.i.Set(value)
}
func (v *Int) Get() int64 {
	return v.i.Get()
}
func (v *Int) String() string {
	return strconv.FormatInt(v.i.Get(), 10)
}
type Duration struct {
	i sync2.AtomicDuration
}
func NewDuration(name string) *Duration {
	v := new(Duration)
	publish(name, v)
	return v
}
func (v *Duration) Add(delta time.Duration) {
	v.i.Add(delta)
}
func (v *Duration) Set(value time.Duration) {
	v.i.Set(value)
}
func (v *Duration) Get() time.Duration {
	return v.i.Get()
}
func (v *Duration) String() string {
	return strconv.FormatInt(int64(v.i.Get()), 10)
}
type IntFunc func() int64
func (f IntFunc) String() string {
	return strconv.FormatInt(f(), 10)
}
type DurationFunc func() time.Duration
func (f DurationFunc) String() string {
	return strconv.FormatInt(int64(f()), 10)
}
type String struct {
	mu sync.Mutex
	s  string
}
func NewString(name string) *String {
	v := new(String)
	publish(name, v)
	return v
}
func (v *String) Set(value string) {
	v.mu.Lock()
	v.s = value
	v.mu.Unlock()
}
func (v *String) Get() string {
	v.mu.Lock()
	s := v.s
	v.mu.Unlock()
	return s
}
func (v *String) String() string {
	return strconv.Quote(v.Get())
}
type StringFunc func() string
func (f StringFunc) String() string {
	return strconv.Quote(f())
}
type JSONFunc func() string
func (f JSONFunc) String() string {
	return f()
}
func PublishJSONFunc(name string, f func() string) {
	publish(name, JSONFunc(f))
}
type StringMap struct {
	mu     sync.Mutex
	values map[string]string
}