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 #pragma once 7 8 #include "monitoring/statistics.h" 9 #include "port/port.h" 10 #include "rocksdb/statistics.h" 11 #include "rocksdb/system_clock.h" 12 #include "rocksdb/thread_status.h" 13 #include "util/stop_watch.h" 14 15 namespace ROCKSDB_NAMESPACE { 16 class InstrumentedCondVar; 17 18 // A wrapper class for port::Mutex that provides additional layer 19 // for collecting stats and instrumentation. 20 class InstrumentedMutex { 21 public: 22 explicit InstrumentedMutex(bool adaptive = false) mutex_(adaptive)23 : mutex_(adaptive), stats_(nullptr), clock_(nullptr), stats_code_(0) {} 24 25 explicit InstrumentedMutex(SystemClock* clock, bool adaptive = false) mutex_(adaptive)26 : mutex_(adaptive), stats_(nullptr), clock_(clock), stats_code_(0) {} 27 28 InstrumentedMutex(Statistics* stats, SystemClock* clock, int stats_code, 29 bool adaptive = false) mutex_(adaptive)30 : mutex_(adaptive), 31 stats_(stats), 32 clock_(clock), 33 stats_code_(stats_code) {} 34 35 void Lock(); 36 Unlock()37 void Unlock() { 38 mutex_.Unlock(); 39 } 40 AssertHeld()41 void AssertHeld() { 42 mutex_.AssertHeld(); 43 } 44 45 private: 46 void LockInternal(); 47 friend class InstrumentedCondVar; 48 port::Mutex mutex_; 49 Statistics* stats_; 50 SystemClock* clock_; 51 int stats_code_; 52 }; 53 54 // RAII wrapper for InstrumentedMutex 55 class InstrumentedMutexLock { 56 public: InstrumentedMutexLock(InstrumentedMutex * mutex)57 explicit InstrumentedMutexLock(InstrumentedMutex* mutex) : mutex_(mutex) { 58 mutex_->Lock(); 59 } 60 ~InstrumentedMutexLock()61 ~InstrumentedMutexLock() { 62 mutex_->Unlock(); 63 } 64 65 private: 66 InstrumentedMutex* const mutex_; 67 InstrumentedMutexLock(const InstrumentedMutexLock&) = delete; 68 void operator=(const InstrumentedMutexLock&) = delete; 69 }; 70 71 // RAII wrapper for temporary releasing InstrumentedMutex inside 72 // InstrumentedMutexLock 73 class InstrumentedMutexUnlock { 74 public: InstrumentedMutexUnlock(InstrumentedMutex * mutex)75 explicit InstrumentedMutexUnlock(InstrumentedMutex* mutex) : mutex_(mutex) { 76 mutex_->Unlock(); 77 } 78 ~InstrumentedMutexUnlock()79 ~InstrumentedMutexUnlock() { mutex_->Lock(); } 80 81 private: 82 InstrumentedMutex* const mutex_; 83 InstrumentedMutexUnlock(const InstrumentedMutexUnlock&) = delete; 84 void operator=(const InstrumentedMutexUnlock&) = delete; 85 }; 86 87 class InstrumentedCondVar { 88 public: InstrumentedCondVar(InstrumentedMutex * instrumented_mutex)89 explicit InstrumentedCondVar(InstrumentedMutex* instrumented_mutex) 90 : cond_(&(instrumented_mutex->mutex_)), 91 stats_(instrumented_mutex->stats_), 92 clock_(instrumented_mutex->clock_), 93 stats_code_(instrumented_mutex->stats_code_) {} 94 95 void Wait(); 96 97 bool TimedWait(uint64_t abs_time_us); 98 Signal()99 void Signal() { 100 cond_.Signal(); 101 } 102 SignalAll()103 void SignalAll() { 104 cond_.SignalAll(); 105 } 106 107 private: 108 void WaitInternal(); 109 bool TimedWaitInternal(uint64_t abs_time_us); 110 port::CondVar cond_; 111 Statistics* stats_; 112 SystemClock* clock_; 113 int stats_code_; 114 }; 115 116 } // namespace ROCKSDB_NAMESPACE 117