mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-26 02:50:54 +00:00
Added all required dependencies
This commit is contained in:
parent
78f86abba4
commit
1ebb35b988
660 changed files with 502447 additions and 0 deletions
144
vendor/github.com/jtolds/gls/context.go
generated
vendored
Normal file
144
vendor/github.com/jtolds/gls/context.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
// Package gls implements goroutine-local storage.
|
||||
package gls
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
maxCallers = 64
|
||||
)
|
||||
|
||||
var (
|
||||
stackTagPool = &idPool{}
|
||||
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.RWMutex
|
||||
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
|
||||
}
|
||||
|
||||
tags := readStackTags(1)
|
||||
|
||||
m.mtx.Lock()
|
||||
values := new_values
|
||||
for _, tag := range tags {
|
||||
if existing_values, ok := m.values[tag]; ok {
|
||||
// oh, we found existing values, let's make a copy
|
||||
values = make(Values, len(existing_values)+len(new_values))
|
||||
for key, val := range existing_values {
|
||||
values[key] = val
|
||||
}
|
||||
for key, val := range new_values {
|
||||
values[key] = val
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
new_tag := stackTagPool.Acquire()
|
||||
m.values[new_tag] = values
|
||||
m.mtx.Unlock()
|
||||
defer func() {
|
||||
m.mtx.Lock()
|
||||
delete(m.values, new_tag)
|
||||
m.mtx.Unlock()
|
||||
stackTagPool.Release(new_tag)
|
||||
}()
|
||||
|
||||
addStackTag(new_tag, 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) {
|
||||
|
||||
tags := readStackTags(1)
|
||||
m.mtx.RLock()
|
||||
defer m.mtx.RUnlock()
|
||||
for _, tag := range tags {
|
||||
if values, ok := m.values[tag]; ok {
|
||||
value, ok := values[key]
|
||||
return value, ok
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (m *ContextManager) getValues() Values {
|
||||
tags := readStackTags(2)
|
||||
m.mtx.RLock()
|
||||
defer m.mtx.RUnlock()
|
||||
for _, tag := range tags {
|
||||
if values, ok := m.values[tag]; ok {
|
||||
return values
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
mgr_copy := mgr
|
||||
cb_copy := cb
|
||||
cb = func() { mgr_copy.SetValues(values, cb_copy) }
|
||||
}
|
||||
}
|
||||
|
||||
go cb()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue