tpl/partials: Fix cache locking

To make sure a cached partial is ony executed  exactly once.

Performance same:

```bash
name                         old time/op    new time/op    delta
TemplateParamsKeysToLower-4    17.2µs ± 0%    16.5µs ± 0%   ~     (p=1.000 n=1+1)
Partial-4                      18.6µs ± 0%    19.4µs ± 0%   ~     (p=1.000 n=1+1)
PartialCached-4                64.2ns ± 0%    63.7ns ± 0%   ~     (p=1.000 n=1+1)

name                         old alloc/op   new alloc/op   delta
TemplateParamsKeysToLower-4    2.66kB ± 0%    2.66kB ± 0%   ~     (all equal)
Partial-4                      1.31kB ± 0%    1.31kB ± 0%   ~     (all equal)
PartialCached-4                 0.00B          0.00B        ~     (all equal)

name                         old allocs/op  new allocs/op  delta
TemplateParamsKeysToLower-4      92.0 ± 0%      92.0 ± 0%   ~     (all equal)
Partial-4                        41.0 ± 0%      41.0 ± 0%   ~     (all equal)
```
This commit is contained in:
Bjørn Erik Pedersen 2017-11-16 01:23:37 +01:00
parent 7730d683e8
commit f5ed04bd4a
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F

View file

@ -110,27 +110,30 @@ func (ns *Namespace) IncludeCached(name string, context interface{}, variant ...
return ns.getOrCreate(key, name, context) return ns.getOrCreate(key, name, context)
} }
func (ns *Namespace) getOrCreate(key, name string, context interface{}) (p interface{}, err error) { func (ns *Namespace) getOrCreate(key, name string, context interface{}) (interface{}, error) {
var ok bool
ns.cachedPartials.RLock() ns.cachedPartials.RLock()
p, ok = ns.cachedPartials.p[key] p, ok := ns.cachedPartials.p[key]
ns.cachedPartials.RUnlock() ns.cachedPartials.RUnlock()
if ok { if ok {
return return p, nil
} }
ns.cachedPartials.Lock() ns.cachedPartials.Lock()
if p, ok = ns.cachedPartials.p[key]; !ok { defer ns.cachedPartials.Unlock()
ns.cachedPartials.Unlock()
p, err = ns.Include(name, context) // Double-check.
if p, ok = ns.cachedPartials.p[key]; ok {
return p, nil
}
p, err := ns.Include(name, context)
if err != nil {
return nil, err
}
ns.cachedPartials.Lock()
ns.cachedPartials.p[key] = p ns.cachedPartials.p[key] = p
} return p, nil
ns.cachedPartials.Unlock()
return
} }