]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/util/mutexlock.h
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / rocksdb / util / mutexlock.h
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
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
17namespace 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
29class 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//
48class 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//
65class 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//
82class 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//
100class 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