validity_map.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package collect
  2. import (
  3. "sync"
  4. "sync/atomic"
  5. "github.com/v2ray/v2ray-core/common/serial"
  6. )
  7. type Validity interface {
  8. IsValid() bool
  9. }
  10. type entry struct {
  11. key string
  12. value Validity
  13. }
  14. type ValidityMap struct {
  15. sync.RWMutex
  16. cache map[string]Validity
  17. opCount int32
  18. }
  19. func NewValidityMap(cleanupIntervalSec int) *ValidityMap {
  20. instance := &ValidityMap{
  21. cache: make(map[string]Validity),
  22. }
  23. return instance
  24. }
  25. func (this *ValidityMap) cleanup() {
  26. entry2Remove := make([]entry, 0, 128)
  27. this.RLock()
  28. for key, value := range this.cache {
  29. if !value.IsValid() {
  30. entry2Remove = append(entry2Remove, entry{
  31. key: key,
  32. value: value,
  33. })
  34. }
  35. }
  36. this.RUnlock()
  37. for _, entry := range entry2Remove {
  38. if !entry.value.IsValid() {
  39. this.Lock()
  40. delete(this.cache, entry.key)
  41. this.Unlock()
  42. }
  43. }
  44. }
  45. func (this *ValidityMap) Set(key serial.String, value Validity) {
  46. this.Lock()
  47. this.cache[key.String()] = value
  48. this.Unlock()
  49. opCount := atomic.AddInt32(&this.opCount, 1)
  50. if opCount > 1000 {
  51. atomic.StoreInt32(&this.opCount, 0)
  52. go this.cleanup()
  53. }
  54. }
  55. func (this *ValidityMap) Get(key serial.String) Validity {
  56. this.RLock()
  57. defer this.RUnlock()
  58. if value, found := this.cache[key.String()]; found {
  59. return value
  60. }
  61. return nil
  62. }