Core components of the web application. https://write.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
1.2 KiB

  1. package memo
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. type (
  7. Memo struct {
  8. f Func
  9. mu sync.Mutex //guards cache
  10. cache *entry
  11. cacheDur time.Duration
  12. lastCache time.Time
  13. }
  14. Func func() (interface{}, error)
  15. )
  16. type (
  17. entry struct {
  18. res result
  19. ready chan struct{} // close when res is read
  20. }
  21. result struct {
  22. value interface{}
  23. err error
  24. }
  25. )
  26. func New(f Func, cd time.Duration) *Memo {
  27. return &Memo{
  28. f: f,
  29. cacheDur: cd,
  30. }
  31. }
  32. // Invalidate resets the cache to nil if the memo's given cache duration has
  33. // elapsed, and returns true if the cache was actually invalidated.
  34. func (memo *Memo) Invalidate() bool {
  35. defer memo.mu.Unlock()
  36. memo.mu.Lock()
  37. if memo.cache != nil && time.Now().Sub(memo.lastCache) > memo.cacheDur {
  38. memo.cache = nil
  39. memo.lastCache = time.Now()
  40. return true
  41. }
  42. return false
  43. }
  44. func (memo *Memo) Get() (value interface{}, err error) {
  45. memo.mu.Lock()
  46. if memo.cache == nil {
  47. memo.cache = &entry{ready: make(chan struct{})}
  48. memo.mu.Unlock()
  49. memo.cache.res.value, memo.cache.res.err = memo.f()
  50. close(memo.cache.ready)
  51. } else {
  52. memo.mu.Unlock()
  53. <-memo.cache.ready
  54. }
  55. return memo.cache.res.value, memo.cache.res.err
  56. }