summaryrefslogtreecommitdiff
path: root/vendor/github.com/getlantern/context/context.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/getlantern/context/context.go')
-rw-r--r--vendor/github.com/getlantern/context/context.go309
1 files changed, 0 insertions, 309 deletions
diff --git a/vendor/github.com/getlantern/context/context.go b/vendor/github.com/getlantern/context/context.go
deleted file mode 100644
index c77f129..0000000
--- a/vendor/github.com/getlantern/context/context.go
+++ /dev/null
@@ -1,309 +0,0 @@
-// Package context provides a mechanism for transparently tracking contextual
-// state associated to the current goroutine and even across goroutines.
-package context
-
-import (
- "sync"
-)
-
-// Manager provides the ability to create and access Contexts.
-type Manager interface {
- // Enter enters a new level on the current Context stack, creating a new Context
- // if necessary.
- Enter() Context
-
- // Go starts the given function on a new goroutine but sharing the context of
- // the current goroutine (if it has one).
- Go(func())
-
- // PutGlobal puts the given key->value pair into the global context.
- PutGlobal(key string, value interface{})
-
- // PutGlobalDynamic puts a key->value pair into the global context where the
- // value is generated by a function that gets evaluated at every Read. If the
- // value is a map[string]interface{}, we will unpack the map and set each
- // contained key->value pair independently.
- PutGlobalDynamic(key string, valueFN func() interface{})
-
- // AsMap returns a map containing all values from the supplied obj if it is a
- // Contextual, plus any addition values from along the stack, plus globals if so
- // specified.
- AsMap(obj interface{}, includeGlobals bool) Map
-}
-
-type manager struct {
- contexts map[uint64]*context
- mxContexts sync.RWMutex
- global Map
- mxGlobal sync.RWMutex
-}
-
-// NewManager creates a new Manager
-func NewManager() Manager {
- return &manager{
- contexts: make(map[uint64]*context),
- global: make(Map),
- }
-}
-
-// Contextual is an interface for anything that maintains its own context.
-type Contextual interface {
- // Fill fills the given Map with all of this Contextual's context
- Fill(m Map)
-}
-
-// Map is a map of key->value pairs.
-type Map map[string]interface{}
-
-// Fill implements the method from the Contextual interface.
-func (_m Map) Fill(m Map) {
- for key, value := range _m {
- m[key] = value
- }
-}
-
-// Context is a context containing key->value pairs
-type Context interface {
- // Enter enters a new level on this Context stack.
- Enter() Context
-
- // Go starts the given function on a new goroutine.
- Go(fn func())
-
- // Exit exits the current level on this Context stack.
- Exit()
-
- // Put puts a key->value pair into the current level of the context stack.
- Put(key string, value interface{}) Context
-
- // PutIfAbsent puts the given key->value pair into the current level of the
- // context stack if and only if that key is defined nowhere within the context
- // stack (including parent contexts).
- PutIfAbsent(key string, value interface{}) Context
-
- // PutDynamic puts a key->value pair into the current level of the context
- // stack where the value is generated by a function that gets evaluated at
- // every Read. If the value is a map[string]interface{}, we will unpack the
- // map and set each contained key->value pair independently.
- PutDynamic(key string, valueFN func() interface{}) Context
-
- // Fill fills the given map with data from this Context
- Fill(m Map)
-
- // AsMap returns a map containing all values from the supplied obj if it is a
- // Contextual, plus any addition values from along the stack, plus globals if
- // so specified.
- AsMap(obj interface{}, includeGlobals bool) Map
-}
-
-type context struct {
- cm *manager
- id uint64
- parent *context
- branchedFrom *context
- data Map
- mx sync.RWMutex
-}
-
-type dynval struct {
- fn func() interface{}
-}
-
-func (cm *manager) Enter() Context {
- return cm.enter(curGoroutineID())
-}
-
-func (cm *manager) enter(id uint64) *context {
- cm.mxContexts.Lock()
- parentOrNil := cm.contexts[id]
- c := cm.makeContext(id, parentOrNil, nil)
- cm.contexts[id] = c
- cm.mxContexts.Unlock()
- return c
-}
-
-func (cm *manager) exit(id uint64, parent *context) {
- cm.mxContexts.Lock()
- if parent == nil {
- delete(cm.contexts, id)
- } else {
- cm.contexts[id] = parent
- }
- cm.mxContexts.Unlock()
-}
-
-func (cm *manager) branch(id uint64, from *context) {
- next := cm.makeContext(id, nil, from)
- cm.mxContexts.Lock()
- cm.contexts[id] = next
- cm.mxContexts.Unlock()
-}
-
-func (cm *manager) merge(id uint64) {
- cm.mxContexts.Lock()
- delete(cm.contexts, id)
- cm.mxContexts.Unlock()
-}
-
-func (c *context) Enter() Context {
- c.mx.RLock()
- id := c.id
- c.mx.RUnlock()
- return c.cm.enter(id)
-}
-
-func (c *context) Go(fn func()) {
- go func() {
- id := curGoroutineID()
- c.cm.branch(id, c)
- fn()
- c.cm.merge(id)
- }()
-}
-
-func (cm *manager) Go(fn func()) {
- c := cm.currentContext()
- if c != nil {
- c.Go(fn)
- } else {
- go fn()
- }
-}
-
-func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context {
- return &context{
- cm: cm,
- id: id,
- parent: parent,
- branchedFrom: branchedFrom,
- data: make(Map),
- }
-}
-
-func (c *context) Exit() {
- c.mx.RLock()
- id := c.id
- parent := c.parent
- c.mx.RUnlock()
- c.cm.exit(id, parent)
-}
-
-func (c *context) Put(key string, value interface{}) Context {
- c.mx.Lock()
- c.data[key] = value
- c.mx.Unlock()
- return c
-}
-
-func (c *context) PutIfAbsent(key string, value interface{}) Context {
- for ctx := c; ctx != nil; {
- ctx.mx.RLock()
- _, exists := ctx.data[key]
- next := ctx.parent
- if next == nil {
- next = ctx.branchedFrom
- }
- ctx.mx.RUnlock()
- if exists {
- return c
- }
- ctx = next
- }
-
- // Value not set, set it
- return c.Put(key, value)
-}
-
-func (c *context) PutDynamic(key string, valueFN func() interface{}) Context {
- value := &dynval{valueFN}
- c.mx.Lock()
- c.data[key] = value
- c.mx.Unlock()
- return c
-}
-
-func (cm *manager) PutGlobal(key string, value interface{}) {
- cm.mxGlobal.Lock()
- cm.global[key] = value
- cm.mxGlobal.Unlock()
-}
-
-func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) {
- value := &dynval{valueFN}
- cm.mxGlobal.Lock()
- cm.global[key] = value
- cm.mxGlobal.Unlock()
-}
-
-func (c *context) Fill(m Map) {
- for ctx := c; ctx != nil; {
- ctx.mx.RLock()
- fill(m, ctx.data)
- next := ctx.parent
- if next == nil {
- next = ctx.branchedFrom
- }
- ctx.mx.RUnlock()
- ctx = next
- }
-}
-
-func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map {
- return cm.currentContext().asMap(cm, obj, includeGlobals)
-}
-
-func (c *context) AsMap(obj interface{}, includeGlobals bool) Map {
- return c.asMap(c.cm, obj, includeGlobals)
-}
-
-func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map {
- result := make(Map, 0)
- cl, ok := obj.(Contextual)
- if ok {
- cl.Fill(result)
- }
- if c != nil {
- c.Fill(result)
- }
- if includeGlobals {
- cm.mxGlobal.RLock()
- fill(result, cm.global)
- cm.mxGlobal.RUnlock()
- }
- return result
-}
-
-func fill(m Map, from Map) {
- if m != nil {
- doFill := func(key string, _value interface{}) {
- switch value := _value.(type) {
- case map[string]interface{}:
- for k, v := range value {
- m[k] = v
- }
- default:
- m[key] = value
- }
- }
-
- for key, value := range from {
- _, alreadyRead := m[key]
- if !alreadyRead {
- switch v := value.(type) {
- case *dynval:
- doFill(key, v.fn())
- default:
- doFill(key, v)
- }
- }
- }
- }
-}
-
-func (cm *manager) currentContext() *context {
- id := curGoroutineID()
- cm.mxContexts.RLock()
- c := cm.contexts[id]
- cm.mxContexts.RUnlock()
- return c
-}