/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/mutexlock.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <atomic> |
27 | | #include <thread> |
28 | | |
29 | | #include "yb/rocksdb/port/port.h" |
30 | | |
31 | | namespace rocksdb { |
32 | | |
33 | | // Helper class that locks a mutex on construction and unlocks the mutex when |
34 | | // the destructor of the MutexLock object is invoked. |
35 | | // |
36 | | // Typical usage: |
37 | | // |
38 | | // void MyClass::MyMethod() { |
39 | | // MutexLock l(&mu_); // mu_ is an instance variable |
40 | | // ... some complex code, possibly with multiple return paths ... |
41 | | // } |
42 | | |
43 | | class MutexLock { |
44 | | public: |
45 | 474M | explicit MutexLock(port::Mutex *mu) : mu_(mu) { |
46 | 474M | this->mu_->Lock(); |
47 | 474M | } |
48 | 474M | ~MutexLock() { this->mu_->Unlock(); } |
49 | | |
50 | | private: |
51 | | port::Mutex *const mu_; |
52 | | // No copying allowed |
53 | | MutexLock(const MutexLock&); |
54 | | void operator=(const MutexLock&); |
55 | | }; |
56 | | |
57 | | // |
58 | | // Acquire a ReadLock on the specified RWMutex. |
59 | | // The Lock will be automatically released then the |
60 | | // object goes out of scope. |
61 | | // |
62 | | class ReadLock { |
63 | | public: |
64 | 948 | explicit ReadLock(port::RWMutex *mu) : mu_(mu) { |
65 | 948 | this->mu_->ReadLock(); |
66 | 948 | } |
67 | 948 | ~ReadLock() { this->mu_->ReadUnlock(); } |
68 | | |
69 | | private: |
70 | | port::RWMutex *const mu_; |
71 | | // No copying allowed |
72 | | ReadLock(const ReadLock&); |
73 | | void operator=(const ReadLock&); |
74 | | }; |
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 | 46.4k | explicit WriteLock(port::RWMutex *mu) : mu_(mu) { |
85 | 46.4k | this->mu_->WriteLock(); |
86 | 46.4k | } |
87 | 46.4k | ~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 | 9.02M | SpinMutex() : locked_(false) {} |
103 | | |
104 | 421M | bool try_lock() { |
105 | 421M | auto currently_locked = locked_.load(std::memory_order_relaxed); |
106 | 421M | return !currently_locked && |
107 | 421M | locked_.compare_exchange_weak(currently_locked, true, |
108 | 421M | std::memory_order_acquire, |
109 | 421M | std::memory_order_relaxed); |
110 | 421M | } |
111 | | |
112 | 21.5M | void lock() { |
113 | 21.5M | for (size_t tries = 0;; ++tries5.67k ) { |
114 | 21.5M | if (try_lock()) { |
115 | | // success |
116 | 21.5M | break; |
117 | 21.5M | } |
118 | 5.67k | port::AsmVolatilePause(); |
119 | 5.67k | if (tries > 100) { |
120 | 8 | std::this_thread::yield(); |
121 | 8 | } |
122 | 5.67k | } |
123 | 21.5M | } |
124 | | |
125 | 421M | void unlock() { locked_.store(false, std::memory_order_release); } |
126 | | |
127 | | private: |
128 | | std::atomic<bool> locked_; |
129 | | }; |
130 | | |
131 | | } // namespace rocksdb |