123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- package gls
- import (
- "sync"
- )
- var (
- mgrRegistry = make(map[*ContextManager]bool)
- mgrRegistryMtx sync.RWMutex
- )
- type Values map[interface{}]interface{}
- type ContextManager struct {
- mtx sync.Mutex
- values map[uint]Values
- }
- func NewContextManager() *ContextManager {
- mgr := &ContextManager{values: make(map[uint]Values)}
- mgrRegistryMtx.Lock()
- defer mgrRegistryMtx.Unlock()
- mgrRegistry[mgr] = true
- return mgr
- }
- func (m *ContextManager) Unregister() {
- mgrRegistryMtx.Lock()
- defer mgrRegistryMtx.Unlock()
- delete(mgrRegistry, m)
- }
- 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()
- })
- }
- 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
- }
- 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()
- }
|