Make Save/Load thread-safe

This commit is contained in:
Alan Shreve 2013-06-30 16:12:31 -07:00
parent 1fc39f1402
commit 66d0db0f9a
2 changed files with 16 additions and 3 deletions

View File

@ -5,3 +5,4 @@ code was contributed.)
Dustin Sallings <dustin@spy.net> Dustin Sallings <dustin@spy.net>
Sergey Shepelev <temotor@gmail.com> Sergey Shepelev <temotor@gmail.com>
Alan Shreve <alan@inconshreveable.com>

View File

@ -871,7 +871,7 @@ func (c *cache) DeleteExpired() {
c.Unlock() c.Unlock()
} }
// Write the cache's items (using Gob) to an io.Writer. // Write cache items (using Gob) to an io.Writer.
func (c *cache) Save(w io.Writer) (err error) { func (c *cache) Save(w io.Writer) (err error) {
enc := gob.NewEncoder(w) enc := gob.NewEncoder(w)
@ -880,10 +880,20 @@ func (c *cache) Save(w io.Writer) (err error) {
err = fmt.Errorf("Error registering item types with Gob library") err = fmt.Errorf("Error registering item types with Gob library")
} }
}() }()
for _, v := range c.items {
// copy out the cache items to a temporary array
// so that we don't have to hold a lock while we do I/O
var objects map[string]*item
c.Lock()
for k, v := range c.items {
objects[k] = v
}
c.Unlock()
for _, v := range objects {
gob.Register(v.Object) gob.Register(v.Object)
} }
err = enc.Encode(&c.items) err = enc.Encode(&objects)
return return
} }
@ -909,12 +919,14 @@ func (c *cache) Load(r io.Reader) error {
items := map[string]*item{} items := map[string]*item{}
err := dec.Decode(&items) err := dec.Decode(&items)
if err == nil { if err == nil {
c.Lock()
for k, v := range items { for k, v := range items {
_, found := c.items[k] _, found := c.items[k]
if !found { if !found {
c.items[k] = v c.items[k] = v
} }
} }
c.Unlock()
} }
return err return err
} }