shithub: hugo

Download patch

ref: f5ed04bd4a2ba1a62482b381470f04aad98375f5
parent: 7730d683e8b030c64c5f986b8166c8e65b777ab3
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Nov 15 20:23:37 EST 2017

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)
```

--- a/tpl/partials/partials.go
+++ b/tpl/partials/partials.go
@@ -110,27 +110,30 @@
 	return ns.getOrCreate(key, name, context)
 }
 
-func (ns *Namespace) getOrCreate(key, name string, context interface{}) (p interface{}, err error) {
-	var ok bool
+func (ns *Namespace) getOrCreate(key, name string, context interface{}) (interface{}, error) {
 
 	ns.cachedPartials.RLock()
-	p, ok = ns.cachedPartials.p[key]
+	p, ok := ns.cachedPartials.p[key]
 	ns.cachedPartials.RUnlock()
 
 	if ok {
-		return
+		return p, nil
 	}
 
 	ns.cachedPartials.Lock()
-	if p, ok = ns.cachedPartials.p[key]; !ok {
-		ns.cachedPartials.Unlock()
-		p, err = ns.Include(name, context)
+	defer ns.cachedPartials.Unlock()
 
-		ns.cachedPartials.Lock()
-		ns.cachedPartials.p[key] = p
+	// 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.Unlock()
 
-	return
+	ns.cachedPartials.p[key] = p
+
+	return p, nil
 }