managedresource.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. package syncx
  2. import "sync"
  3. // A ManagedResource is used to manage a resource that might be broken and refetched, like a connection.
  4. type ManagedResource struct {
  5. resource interface{}
  6. lock sync.RWMutex
  7. generate func() interface{}
  8. equals func(a, b interface{}) bool
  9. }
  10. // NewManagedResource returns a ManagedResource.
  11. func NewManagedResource(generate func() interface{}, equals func(a, b interface{}) bool) *ManagedResource {
  12. return &ManagedResource{
  13. generate: generate,
  14. equals: equals,
  15. }
  16. }
  17. // MarkBroken marks the resource broken.
  18. func (mr *ManagedResource) MarkBroken(resource interface{}) {
  19. mr.lock.Lock()
  20. defer mr.lock.Unlock()
  21. if mr.equals(mr.resource, resource) {
  22. mr.resource = nil
  23. }
  24. }
  25. // Take takes the resource, if not loaded, generates it.
  26. func (mr *ManagedResource) Take() interface{} {
  27. mr.lock.RLock()
  28. resource := mr.resource
  29. mr.lock.RUnlock()
  30. if resource != nil {
  31. return resource
  32. }
  33. mr.lock.Lock()
  34. defer mr.lock.Unlock()
  35. // maybe another Take() call already generated the resource.
  36. if mr.resource == nil {
  37. mr.resource = mr.generate()
  38. }
  39. return mr.resource
  40. }