diff options
Diffstat (limited to 'vendor/github.com/jtolds/gls/context.go')
-rw-r--r-- | vendor/github.com/jtolds/gls/context.go | 153 |
1 files changed, 0 insertions, 153 deletions
diff --git a/vendor/github.com/jtolds/gls/context.go b/vendor/github.com/jtolds/gls/context.go deleted file mode 100644 index 618a171..0000000 --- a/vendor/github.com/jtolds/gls/context.go +++ /dev/null @@ -1,153 +0,0 @@ -// Package gls implements goroutine-local storage. -package gls - -import ( - "sync" -) - -var ( - mgrRegistry = make(map[*ContextManager]bool) - mgrRegistryMtx sync.RWMutex -) - -// Values is simply a map of key types to value types. Used by SetValues to -// set multiple values at once. -type Values map[interface{}]interface{} - -// ContextManager is the main entrypoint for interacting with -// Goroutine-local-storage. You can have multiple independent ContextManagers -// at any given time. ContextManagers are usually declared globally for a given -// class of context variables. You should use NewContextManager for -// construction. -type ContextManager struct { - mtx sync.Mutex - values map[uint]Values -} - -// NewContextManager returns a brand new ContextManager. It also registers the -// new ContextManager in the ContextManager registry which is used by the Go -// method. ContextManagers are typically defined globally at package scope. -func NewContextManager() *ContextManager { - mgr := &ContextManager{values: make(map[uint]Values)} - mgrRegistryMtx.Lock() - defer mgrRegistryMtx.Unlock() - mgrRegistry[mgr] = true - return mgr -} - -// Unregister removes a ContextManager from the global registry, used by the -// Go method. Only intended for use when you're completely done with a -// ContextManager. Use of Unregister at all is rare. -func (m *ContextManager) Unregister() { - mgrRegistryMtx.Lock() - defer mgrRegistryMtx.Unlock() - delete(mgrRegistry, m) -} - -// SetValues takes a collection of values and a function to call for those -// values to be set in. Anything further down the stack will have the set -// values available through GetValue. SetValues will add new values or replace -// existing values of the same key and will not mutate or change values for -// previous stack frames. -// SetValues is slow (makes a copy of all current and new values for the new -// gls-context) in order to reduce the amount of lookups GetValue requires. -func (m *ContextManager) SetValues(new_values Values, context_call func()) { - if len(new_values) == 0 { - context_call() - return - } - - mutated_keys := make([]interface{}, 0, len(new_values)) - mutated_vals := make(Values, len(new_values)) - - EnsureGoroutineId(func(gid uint) { - m.mtx.Lock() - state, found := m.values[gid] - if !found { - state = make(Values, len(new_values)) - m.values[gid] = state - } - m.mtx.Unlock() - - for key, new_val := range new_values { - mutated_keys = append(mutated_keys, key) - if old_val, ok := state[key]; ok { - mutated_vals[key] = old_val - } - state[key] = new_val - } - - defer func() { - if !found { - m.mtx.Lock() - delete(m.values, gid) - m.mtx.Unlock() - return - } - - for _, key := range mutated_keys { - if val, ok := mutated_vals[key]; ok { - state[key] = val - } else { - delete(state, key) - } - } - }() - - context_call() - }) -} - -// GetValue will return a previously set value, provided that the value was set -// by SetValues somewhere higher up the stack. If the value is not found, ok -// will be false. -func (m *ContextManager) GetValue(key interface{}) ( - value interface{}, ok bool) { - gid, ok := GetGoroutineId() - if !ok { - return nil, false - } - - m.mtx.Lock() - state, found := m.values[gid] - m.mtx.Unlock() - - if !found { - return nil, false - } - value, ok = state[key] - return value, ok -} - -func (m *ContextManager) getValues() Values { - gid, ok := GetGoroutineId() - if !ok { - return nil - } - m.mtx.Lock() - state, _ := m.values[gid] - m.mtx.Unlock() - return state -} - -// Go preserves ContextManager values and Goroutine-local-storage across new -// goroutine invocations. The Go method makes a copy of all existing values on -// all registered context managers and makes sure they are still set after -// kicking off the provided function in a new goroutine. If you don't use this -// Go method instead of the standard 'go' keyword, you will lose values in -// ContextManagers, as goroutines have brand new stacks. -func Go(cb func()) { - mgrRegistryMtx.RLock() - defer mgrRegistryMtx.RUnlock() - - for mgr := range mgrRegistry { - values := mgr.getValues() - if len(values) > 0 { - cb = func(mgr *ContextManager, cb func()) func() { - return func() { mgr.SetValues(values, cb) } - }(mgr, cb) - } - } - - go cb() -} |