Path: blob/master/common/lazycontainer.go
508 views
package common12import (3"sync"4"sync/atomic"5"unsafe"6)78// LazyContainer is a lazy datastructure that allows a single evaluation of a given function9type LazyContainer struct {10// Get returns the value generated by the function (computes it if needed)11Get func() unsafe.Pointer12}1314const (15empty uint32 = iota16gettingReady17ready18)1920// NewLazyContainer returns a LazyContainer that will contain the result of the given fonction21func NewLazyContainer(f func() unsafe.Pointer) *LazyContainer {22lc := LazyContainer{}23var content unsafe.Pointer24var mtx sync.Mutex2526status := empty2728prepare := func() unsafe.Pointer {29mtx.Lock()30value := f()31atomic.StorePointer(&content, value)3233// next getters doesn't need to look at any lock34defer atomic.StoreUint32(&status, ready)35defer mtx.Unlock()36return value37}3839lc.Get = func() unsafe.Pointer {40if atomic.LoadUint32(&status) != ready {41if atomic.CompareAndSwapUint32(&status, empty, gettingReady) {42return prepare()43}44// IT IS GETTING READY45// tries to acquire the lock and release it46for atomic.LoadUint32(&status) != ready {47mtx.Lock()48mtx.Unlock()49}50}5152return atomic.LoadPointer(&content)53}5455return &lc56}575859