multi_resource_lock.cpp 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. #include "multi_resource_lock.h"
  2. using namespace NYql;
  3. TMultiResourceLock::TResourceLock TMultiResourceLock::Acquire(TString resourceId) {
  4. TLock::TPtr lock = ProvideResourceLock(resourceId);
  5. // resource-specific mutex should be locked outside of Guard_ lock
  6. return { *this, std::move(lock), std::move(resourceId) };
  7. }
  8. TMultiResourceLock::~TMultiResourceLock() {
  9. with_lock(Guard_) {
  10. Y_ABORT_UNLESS(Locks_.empty(), "~TMultiResourceLock: we still have %lu unreleased locks", Locks_.size());
  11. }
  12. }
  13. TMultiResourceLock::TLock::TPtr TMultiResourceLock::ProvideResourceLock(const TString& resourceId) {
  14. with_lock(Guard_) {
  15. auto it = Locks_.find(resourceId);
  16. if (it == Locks_.end()) {
  17. it = Locks_.emplace(resourceId, MakeIntrusive<TLock>()).first;
  18. }
  19. // important: ref count will be incremented under lock
  20. // in this case we have guarantee TryCleanup will not erase this resource just after exit from this method and before entering lock->Mutex_.Acquire()
  21. return it->second;
  22. }
  23. }
  24. void TMultiResourceLock::TryCleanup(const TString& resourceId) {
  25. with_lock(Guard_) {
  26. auto it = Locks_.find(resourceId);
  27. if (it == Locks_.end()) {
  28. return;
  29. }
  30. if (it->second->IsUnique()) {
  31. Locks_.erase(it);
  32. }
  33. }
  34. }