]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/mutexlock.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / util / mutexlock.h
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 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 #pragma once
11 #include <assert.h>
12 #include <atomic>
13 #include <mutex>
14 #include <thread>
15 #include "port/port.h"
16
17 namespace rocksdb {
18
19 // Helper class that locks a mutex on construction and unlocks the mutex when
20 // the destructor of the MutexLock object is invoked.
21 //
22 // Typical usage:
23 //
24 // void MyClass::MyMethod() {
25 // MutexLock l(&mu_); // mu_ is an instance variable
26 // ... some complex code, possibly with multiple return paths ...
27 // }
28
29 class MutexLock {
30 public:
31 explicit MutexLock(port::Mutex *mu) : mu_(mu) {
32 this->mu_->Lock();
33 }
34 ~MutexLock() { this->mu_->Unlock(); }
35
36 private:
37 port::Mutex *const mu_;
38 // No copying allowed
39 MutexLock(const MutexLock&);
40 void operator=(const MutexLock&);
41 };
42
43 //
44 // Acquire a ReadLock on the specified RWMutex.
45 // The Lock will be automatically released then the
46 // object goes out of scope.
47 //
48 class ReadLock {
49 public:
50 explicit ReadLock(port::RWMutex *mu) : mu_(mu) {
51 this->mu_->ReadLock();
52 }
53 ~ReadLock() { this->mu_->ReadUnlock(); }
54
55 private:
56 port::RWMutex *const mu_;
57 // No copying allowed
58 ReadLock(const ReadLock&);
59 void operator=(const ReadLock&);
60 };
61
62 //
63 // Automatically unlock a locked mutex when the object is destroyed
64 //
65 class ReadUnlock {
66 public:
67 explicit ReadUnlock(port::RWMutex *mu) : mu_(mu) { mu->AssertHeld(); }
68 ~ReadUnlock() { mu_->ReadUnlock(); }
69
70 private:
71 port::RWMutex *const mu_;
72 // No copying allowed
73 ReadUnlock(const ReadUnlock &) = delete;
74 ReadUnlock &operator=(const ReadUnlock &) = delete;
75 };
76
77 //
78 // Acquire a WriteLock on the specified RWMutex.
79 // The Lock will be automatically released then the
80 // object goes out of scope.
81 //
82 class WriteLock {
83 public:
84 explicit WriteLock(port::RWMutex *mu) : mu_(mu) {
85 this->mu_->WriteLock();
86 }
87 ~WriteLock() { this->mu_->WriteUnlock(); }
88
89 private:
90 port::RWMutex *const mu_;
91 // No copying allowed
92 WriteLock(const WriteLock&);
93 void operator=(const WriteLock&);
94 };
95
96 //
97 // SpinMutex has very low overhead for low-contention cases. Method names
98 // are chosen so you can use std::unique_lock or std::lock_guard with it.
99 //
100 class SpinMutex {
101 public:
102 SpinMutex() : locked_(false) {}
103
104 bool try_lock() {
105 auto currently_locked = locked_.load(std::memory_order_relaxed);
106 return !currently_locked &&
107 locked_.compare_exchange_weak(currently_locked, true,
108 std::memory_order_acquire,
109 std::memory_order_relaxed);
110 }
111
112 void lock() {
113 for (size_t tries = 0;; ++tries) {
114 if (try_lock()) {
115 // success
116 break;
117 }
118 port::AsmVolatilePause();
119 if (tries > 100) {
120 std::this_thread::yield();
121 }
122 }
123 }
124
125 void unlock() { locked_.store(false, std::memory_order_release); }
126
127 private:
128 std::atomic<bool> locked_;
129 };
130
131 } // namespace rocksdb