// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package memoize supports memoizing the return values of functions with
// idempotent results that are expensive to compute.
//
// The memoized result is returned again the next time the function is invoked.
// To prevent excessive memory use, the return values are only remembered
// for as long as they still have a user.
//
// To use this package, build a store and use it to acquire handles with the
// Bind method.
//
package memoize

import (
	"context"
	"runtime"
	"sync"
	"unsafe"

	"golang.org/x/tools/internal/xcontext"
)

// Store binds keys to functions, returning handles that can be used to access
// the functions results.
type Store struct {
	mu sync.Mutex
	// entries is the set of values stored.
	entries map[interface{}]uintptr
}

// Function is the type for functions that can be memoized.
// The result must be a pointer.
type Function func(ctx context.Context) interface{}

type state int

const (
	stateIdle = iota
	stateRunning
	stateCompleted
)

// Handle is returned from a store when a key is bound to a function.
// It is then used to access the results of that function.
//
// A Handle starts out in idle state, waiting for something to demand its
// evaluation. It then transitions into running state. While it's running,
// waiters tracks the number of Get calls waiting for a result, and the done
// channel is used to notify waiters of the next state transition. Once the
// evaluation finishes, value is set, state changes to completed, and done
// is closed, unblocking waiters. Alternatively, as Get calls are cancelled,
// they decrement waiters. If it drops to zero, the inner context is cancelled,
// computation is abandoned, and state resets to idle to start the process over
// again.
type Handle struct {
	store *Store
	key   interface{}

	mu    sync.Mutex
	state state
	// done is set in running state, and closed when exiting it.
	done chan struct{}
	// cancel is set in running state. It cancels computation.
	cancel context.CancelFunc
	// waiters is the number of Gets outstanding.
	waiters uint
	// the function that will be used to populate the value
	function Function
	// value is set in completed state.
	value interface{}
}

// Has returns true if they key is currently valid for this store.
func (s *Store) Has(key interface{}) bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	_, found := s.entries[key]
	return found
}

// Bind returns a handle for the given key and function.
//
// Each call to bind will return the same handle if it is already bound.
// Bind will always return a valid handle, creating one if needed.
// Each key can only have one handle at any given time.
// The value will be held for as long as the handle is, once it has been
// generated.
// Bind does not cause the value to be generated.
func (s *Store) Bind(key interface{}, function Function) *Handle {
	// panic early if the function is nil
	// it would panic later anyway, but in a way that was much harder to debug
	if function == nil {
		panic("the function passed to bind must not be nil")
	}
	// check if we already have the key
	s.mu.Lock()
	defer s.mu.Unlock()
	h := s.get(key)
	if h != nil {
		// we have a handle already, just return it
		return h
	}
	// we have not seen this key before, add a new entry
	if s.entries == nil {
		s.entries = make(map[interface{}]uintptr)
	}
	h = &Handle{
		store:    s,
		key:      key,
		function: function,
	}
	// now add the weak reference to the handle into the map
	s.entries[key] = uintptr(unsafe.Pointer(h))
	// add the deletion the entry when the handle is garbage collected
	runtime.SetFinalizer(h, release)
	return h
}

// Find returns the handle associated with a key, if it is bound.
//
// It cannot cause a new handle to be generated, and thus may return nil.
func (s *Store) Find(key interface{}) *Handle {
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.get(key)
}

// Cached returns the value associated with a key.
//
// It cannot cause the value to be generated.
// It will return the cached value, if present.
func (s *Store) Cached(key interface{}) interface{} {
	h := s.Find(key)
	if h == nil {
		return nil
	}
	return h.Cached()
}

//go:nocheckptr
// nocheckptr because: https://github.com/golang/go/issues/35125#issuecomment-545671062
func (s *Store) get(key interface{}) *Handle {
	// this must be called with the store mutex already held
	e, found := s.entries[key]
	if !found {
		return nil
	}
	return (*Handle)(unsafe.Pointer(e))
}

// Cached returns the value associated with a handle.
//
// It will never cause the value to be generated.
// It will return the cached value, if present.
func (h *Handle) Cached() interface{} {
	h.mu.Lock()
	defer h.mu.Unlock()
	if h.state == stateCompleted {
		return h.value
	}
	return nil
}

// Get returns the value associated with a handle.
//
// If the value is not yet ready, the underlying function will be invoked.
// This activates the handle, and it will remember the value for as long as it exists.
// If ctx is cancelled, Get returns nil.
func (h *Handle) Get(ctx context.Context) interface{} {
	if ctx.Err() != nil {
		return nil
	}
	h.mu.Lock()
	switch h.state {
	case stateIdle:
		return h.run(ctx)
	case stateRunning:
		return h.wait(ctx)
	case stateCompleted:
		defer h.mu.Unlock()
		return h.value
	default:
		panic("unknown state")
	}
}

// run starts h.function and returns the result. h.mu must be locked.
func (h *Handle) run(ctx context.Context) interface{} {
	childCtx, cancel := context.WithCancel(xcontext.Detach(ctx))
	h.cancel = cancel
	h.state = stateRunning
	h.done = make(chan struct{})
	function := h.function // Read under the lock
	go func() {
		// Just in case the function does something expensive without checking
		// the context, double-check we're still alive.
		if childCtx.Err() != nil {
			return
		}
		v := function(childCtx)
		if childCtx.Err() != nil {
			return
		}

		h.mu.Lock()
		defer h.mu.Unlock()
		// It's theoretically possible that the handle has been cancelled out
		// of the run that started us, and then started running again since we
		// checked childCtx above. Even so, that should be harmless, since each
		// run should produce the same results.
		if h.state != stateRunning {
			return
		}
		h.value = v
		h.function = nil
		h.state = stateCompleted
		close(h.done)
	}()

	return h.wait(ctx)
}

// wait waits for the value to be computed, or ctx to be cancelled. h.mu must be locked.
func (h *Handle) wait(ctx context.Context) interface{} {
	h.waiters++
	done := h.done
	h.mu.Unlock()

	select {
	case <-done:
		h.mu.Lock()
		defer h.mu.Unlock()
		if h.state == stateCompleted {
			return h.value
		}
		return nil
	case <-ctx.Done():
		h.mu.Lock()
		defer h.mu.Unlock()
		h.waiters--
		if h.waiters == 0 && h.state == stateRunning {
			h.cancel()
			close(h.done)
			h.state = stateIdle
			h.done = nil
			h.cancel = nil
		}
		return nil
	}
}

func release(p interface{}) {
	h := p.(*Handle)
	h.store.mu.Lock()
	defer h.store.mu.Unlock()
	// there is a small gap between the garbage collector deciding that the handle
	// is liable for collection and the finalizer being called
	// if the handle is recovered during that time, you will end up with a valid
	// handle that no longer has an entry in the map, and that no longer has a
	// finalizer associated with it, but that is okay.
	delete(h.store.entries, h.key)
}
