diff --git a/context/attributes.go b/context/attributes.go index 696fc83..cf14d3a 100644 --- a/context/attributes.go +++ b/context/attributes.go @@ -1,20 +1,28 @@ package context +import "sync" + type AttributeManager interface { Init() SetAttribute(key string, value interface{}) GetAttribute(key string) (value interface{}) - GetAttributeNames() []string RemoveAttribute(key string) Contains(key string) (exist bool) Destroy() } type AttributeManagers struct { + Parent AttributeManager attributes map[string]interface{} + + mtx sync.RWMutex } func (am *AttributeManagers) Init() { + if nil != am.Parent { + am.Parent.Init() + } + if nil == am.attributes { am.Destroy() } @@ -22,48 +30,76 @@ func (am *AttributeManagers) Init() { } func (am *AttributeManagers) SetAttribute(key string, value interface{}) { - if nil == am.attributes { - am.attributes = make(map[string]interface{}) - } + am.checkInitialized() + + am.mtx.Lock() + defer am.mtx.Unlock() + am.attributes[key] = value } func (am *AttributeManagers) GetAttribute(key string) (value interface{}) { - if nil == am.attributes { - return nil - } - return am.attributes[key] -} + am.checkInitialized() -func (am *AttributeManagers) GetAttributeNames() []string { - if nil == am.attributes { - return nil - } - keys := []string{} - for k, _ := range am.attributes { - keys = append(keys, k) + am.mtx.RLock() + defer am.mtx.RUnlock() + + if _, ok := am.attributes[key]; ok { + return am.attributes[key] } - return keys + if nil == am.Parent { + return nil + } + return am.Parent.GetAttribute(key) } func (am *AttributeManagers) RemoveAttribute(key string) { - if nil == am.attributes { + am.checkInitialized() + + am.mtx.Lock() + defer am.mtx.Unlock() + + if _, ok := am.attributes[key]; ok { + delete(am.attributes, key) return } - delete(am.attributes, key) + + if nil == am.Parent { + return + } + + am.Parent.RemoveAttribute(key) } func (am *AttributeManagers) Contains(key string) (exist bool) { - if nil == am.attributes { + am.checkInitialized() + + am.mtx.RLock() + defer am.mtx.RUnlock() + + if _, ok := am.attributes[key]; ok { + return true + } + + if nil == am.Parent { return false } - _, ok := am.attributes[key] - return ok + return am.Parent.Contains(key) } func (am *AttributeManagers) Destroy() { if nil != am.attributes { am.attributes = nil } + + if nil != am.Parent { + am.Parent.Destroy() + } +} + +func (am *AttributeManagers) checkInitialized() { + if nil == am.attributes { + panic("Attribute Manager: must be initialized") + } }