]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/utilities/transactions/transaction_db_mutex_impl.cc
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / utilities / transactions / transaction_db_mutex_impl.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5
6 #ifndef ROCKSDB_LITE
7
8 #include "utilities/transactions/transaction_db_mutex_impl.h"
9
10 #include <chrono>
11 #include <condition_variable>
12 #include <functional>
13 #include <mutex>
14
15 #include "rocksdb/utilities/transaction_db_mutex.h"
16
17 namespace rocksdb {
18
19 class TransactionDBMutexImpl : public TransactionDBMutex {
20 public:
21 TransactionDBMutexImpl() {}
22 ~TransactionDBMutexImpl() override {}
23
24 Status Lock() override;
25
26 Status TryLockFor(int64_t timeout_time) override;
27
28 void UnLock() override { mutex_.unlock(); }
29
30 friend class TransactionDBCondVarImpl;
31
32 private:
33 std::mutex mutex_;
34 };
35
36 class TransactionDBCondVarImpl : public TransactionDBCondVar {
37 public:
38 TransactionDBCondVarImpl() {}
39 ~TransactionDBCondVarImpl() override {}
40
41 Status Wait(std::shared_ptr<TransactionDBMutex> mutex) override;
42
43 Status WaitFor(std::shared_ptr<TransactionDBMutex> mutex,
44 int64_t timeout_time) override;
45
46 void Notify() override { cv_.notify_one(); }
47
48 void NotifyAll() override { cv_.notify_all(); }
49
50 private:
51 std::condition_variable cv_;
52 };
53
54 std::shared_ptr<TransactionDBMutex>
55 TransactionDBMutexFactoryImpl::AllocateMutex() {
56 return std::shared_ptr<TransactionDBMutex>(new TransactionDBMutexImpl());
57 }
58
59 std::shared_ptr<TransactionDBCondVar>
60 TransactionDBMutexFactoryImpl::AllocateCondVar() {
61 return std::shared_ptr<TransactionDBCondVar>(new TransactionDBCondVarImpl());
62 }
63
64 Status TransactionDBMutexImpl::Lock() {
65 mutex_.lock();
66 return Status::OK();
67 }
68
69 Status TransactionDBMutexImpl::TryLockFor(int64_t timeout_time) {
70 bool locked = true;
71
72 if (timeout_time == 0) {
73 locked = mutex_.try_lock();
74 } else {
75 // Previously, this code used a std::timed_mutex. However, this was changed
76 // due to known bugs in gcc versions < 4.9.
77 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562
78 //
79 // Since this mutex isn't held for long and only a single mutex is ever
80 // held at a time, it is reasonable to ignore the lock timeout_time here
81 // and only check it when waiting on the condition_variable.
82 mutex_.lock();
83 }
84
85 if (!locked) {
86 // timeout acquiring mutex
87 return Status::TimedOut(Status::SubCode::kMutexTimeout);
88 }
89
90 return Status::OK();
91 }
92
93 Status TransactionDBCondVarImpl::Wait(
94 std::shared_ptr<TransactionDBMutex> mutex) {
95 auto mutex_impl = reinterpret_cast<TransactionDBMutexImpl*>(mutex.get());
96
97 std::unique_lock<std::mutex> lock(mutex_impl->mutex_, std::adopt_lock);
98 cv_.wait(lock);
99
100 // Make sure unique_lock doesn't unlock mutex when it destructs
101 lock.release();
102
103 return Status::OK();
104 }
105
106 Status TransactionDBCondVarImpl::WaitFor(
107 std::shared_ptr<TransactionDBMutex> mutex, int64_t timeout_time) {
108 Status s;
109
110 auto mutex_impl = reinterpret_cast<TransactionDBMutexImpl*>(mutex.get());
111 std::unique_lock<std::mutex> lock(mutex_impl->mutex_, std::adopt_lock);
112
113 if (timeout_time < 0) {
114 // If timeout is negative, do not use a timeout
115 cv_.wait(lock);
116 } else {
117 auto duration = std::chrono::microseconds(timeout_time);
118 auto cv_status = cv_.wait_for(lock, duration);
119
120 // Check if the wait stopped due to timing out.
121 if (cv_status == std::cv_status::timeout) {
122 s = Status::TimedOut(Status::SubCode::kMutexTimeout);
123 }
124 }
125
126 // Make sure unique_lock doesn't unlock mutex when it destructs
127 lock.release();
128
129 // CV was signaled, or we spuriously woke up (but didn't time out)
130 return s;
131 }
132
133 } // namespace rocksdb
134
135 #endif // ROCKSDB_LITE