diff --git a/context.go b/context.go index fe5b6ad..3db3b90 100644 --- a/context.go +++ b/context.go @@ -10,39 +10,59 @@ import ( "time" ) -var ( - mutex sync.Mutex - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) -) +var globalContext *Context = NewContext() + +type Context struct { + mutex sync.RWMutex + data map[*http.Request]map[interface{}]interface{} + datat map[*http.Request]int64 +} + +func NewContext() *Context { + data := make(map[*http.Request]map[interface{}]interface{}) + datat := make(map[*http.Request]int64) + return &Context{data: data, datat: datat} +} // Set stores a value for a given key in a given request. func Set(r *http.Request, key, val interface{}) { - mutex.Lock() - defer mutex.Unlock() - if data[r] == nil { - data[r] = make(map[interface{}]interface{}) - datat[r] = time.Now().Unix() + globalContext.Set(r, key, val) +} + +func (c *Context) Set(r *http.Request, key, val interface{}) { + c.mutex.Lock() + defer c.mutex.Unlock() + if c.data[r] == nil { + c.data[r] = make(map[interface{}]interface{}) + c.datat[r] = time.Now().Unix() } - data[r][key] = val + c.data[r][key] = val } // Get returns a value stored for a given key in a given request. func Get(r *http.Request, key interface{}) interface{} { - mutex.Lock() - defer mutex.Unlock() - if data[r] != nil { - return data[r][key] + return globalContext.Get(r, key) +} + +func (c *Context) Get(r *http.Request, key interface{}) interface{} { + c.mutex.RLock() + defer c.mutex.RUnlock() + if c.data[r] != nil { + return c.data[r][key] } return nil } // Delete removes a value stored for a given key in a given request. func Delete(r *http.Request, key interface{}) { - mutex.Lock() - defer mutex.Unlock() - if data[r] != nil { - delete(data[r], key) + globalContext.Delete(r, key) +} + +func (c *Context) Delete(r *http.Request, key interface{}) { + c.mutex.Lock() + defer c.mutex.Unlock() + if c.data[r] != nil { + delete(c.data[r], key) } } @@ -51,15 +71,19 @@ func Delete(r *http.Request, key interface{}) { // This is usually called by a handler wrapper to clean up request // variables at the end of a request lifetime. See ClearHandler(). func Clear(r *http.Request) { - mutex.Lock() - defer mutex.Unlock() - clear(r) + globalContext.Clear(r) +} + +func (c *Context) Clear(r *http.Request) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.clear(r) } // clear is Clear without the lock. -func clear(r *http.Request) { - delete(data, r) - delete(datat, r) +func (c *Context) clear(r *http.Request) { + delete(c.data, r) + delete(c.datat, r) } // Purge removes request data stored for longer than maxAge, in seconds. @@ -72,18 +96,22 @@ func clear(r *http.Request) { // amount of memory. In case this is detected, Purge() must be called // periodically until the problem is fixed. func Purge(maxAge int) int { - mutex.Lock() - defer mutex.Unlock() + return globalContext.Purge(maxAge) +} + +func (c *Context) Purge(maxAge int) int { + c.mutex.Lock() + defer c.mutex.Unlock() count := 0 if maxAge <= 0 { - count = len(data) - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) + count = len(c.data) + c.data = make(map[*http.Request]map[interface{}]interface{}) + c.datat = make(map[*http.Request]int64) } else { min := time.Now().Unix() - int64(maxAge) - for r, _ := range data { - if datat[r] < min { - clear(r) + for r, _ := range c.data { + if c.datat[r] < min { + c.clear(r) count++ } }