blob: 61804fa9a497edf18c5a2b40db547b1a6b33116d (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
#pragma once
#include "yql_panic.h"
#include <util/generic/map.h>
#include <util/generic/ptr.h>
#include <util/generic/string.h>
#include <util/system/mutex.h>
namespace NYql {
class TMultiResourceLock : private TNonCopyable {
private:
struct TLock : public TThrRefBase {
typedef TIntrusivePtr<TLock> TPtr;
bool IsUnique() const {
return RefCount() == 1;
}
TMutex Mutex_;
};
public:
struct TResourceLock : private TNonCopyable {
TResourceLock(TMultiResourceLock& owner, TLock::TPtr lock, TString resourceId)
: Owner_(owner)
, Lock_(std::move(lock))
, ResourceId_(std::move(resourceId))
{
Y_ENSURE(Lock_);
Lock_->Mutex_.Acquire();
}
TResourceLock(TResourceLock&& other)
: Owner_(other.Owner_)
, Lock_(std::move(other.Lock_))
, ResourceId_(std::move(other.ResourceId_))
{
}
TResourceLock& operator=(TResourceLock&&) = delete;
~TResourceLock() {
if (!Lock_) {
return;
}
Lock_->Mutex_.Release();
// decrement ref count before TryCleanup
Lock_ = nullptr;
Owner_.TryCleanup(ResourceId_);
}
private:
TMultiResourceLock& Owner_;
TLock::TPtr Lock_;
TString ResourceId_;
};
TResourceLock Acquire(TString resourceId);
template <typename F>
auto RunWithLock(TString resourceId, const F& f) -> decltype(f()) {
auto lock = Acquire(std::move(resourceId));
return f();
}
~TMultiResourceLock();
private:
TLock::TPtr ProvideResourceLock(const TString& resourceId);
void TryCleanup(const TString& resourceId);
private:
TMutex Guard_;
TMap<TString, TLock::TPtr> Locks_;
};
}
|