Skip to content

Instantly share code, notes, and snippets.

@CAFxX
Last active September 26, 2023 01:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CAFxX/e6be5a72307786513dbdb95a4de37f1e to your computer and use it in GitHub Desktop.
Save CAFxX/e6be5a72307786513dbdb95a4de37f1e to your computer and use it in GitHub Desktop.
textproto.CanonincalMIMEHeaderKey with memoization and GC
package textproto
import (
"net/textproto"
"runtime"
"sync"
)
// CanonincalMIMEHeaderKey is like textproto.CanonicalMIMEHeaderKey but it
// memoizes results to avoid repeated allocations of the same string.
//
// The memoization is thread-safe and lazily cleaned up when the GC runs.
func CanonincalMIMEHeaderKey(k string) string {
m.RLock()
ck, ok := c[k]
if ok {
m.RUnlock()
return ck
}
ck, ok = o[k]
m.RUnlock()
if !ok {
ck = textproto.CanonicalMIMEHeaderKey(k)
}
m.Lock()
if c == nil {
c = make(map[string]string, len(o))
if o == nil {
defer runtime.SetFinalizer(new(canary), finalizer)
}
}
c[k] = ck
m.Unlock()
return ck
}
var (
m sync.RWMutex // protects the following variables
c map[string]string // current map
o map[string]string // previous map
)
type canary [16]byte
func finalizer(x *canary) {
go func() {
m.Lock()
if c != nil {
o, c = c, nil
defer runtime.SetFinalizer(x, finalizer) // rearm finalizer
} else {
o = nil
}
m.Unlock()
}()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment