SQLiteMutex.h (3886B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_storage_SQLiteMutex_h_ 8 #define mozilla_storage_SQLiteMutex_h_ 9 10 #include "mozilla/BlockingResourceBase.h" 11 #include "sqlite3.h" 12 13 namespace mozilla { 14 namespace storage { 15 16 /** 17 * Wrapper class for sqlite3_mutexes. To be used whenever we want to use a 18 * sqlite3_mutex. 19 * 20 * @warning Never EVER wrap the same sqlite3_mutex with a different SQLiteMutex. 21 * If you do this, you void the deadlock detector's warranty! 22 */ 23 class SQLiteMutex : private BlockingResourceBase { 24 public: 25 /** 26 * Constructs a wrapper for a sqlite3_mutex that has deadlock detecting. 27 * 28 * @param aName 29 * A name which can be used to reference this mutex. 30 */ 31 explicit SQLiteMutex(const char* aName) 32 : BlockingResourceBase(aName, eMutex), mMutex(nullptr) {} 33 34 /** 35 * Sets the mutex that we are wrapping. We generally do not have access to 36 * our mutex at class construction, so we have to set it once we get access to 37 * it. 38 * 39 * @param aMutex 40 * The sqlite3_mutex that we are going to wrap. 41 */ 42 void initWithMutex(sqlite3_mutex* aMutex) { 43 MOZ_ASSERT(aMutex, "You must pass in a valid mutex!"); 44 MOZ_ASSERT(!mMutex, "A mutex has already been set for this!"); 45 mMutex = aMutex; 46 } 47 48 /** 49 * After a connection has been successfully closed, its mutex is a dangling 50 * pointer, and as such it should be destroyed. 51 */ 52 void destroy() { mMutex = NULL; } 53 54 /** 55 * Acquires the mutex. 56 */ 57 void lock() { 58 MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); 59 #if defined(DEBUG) 60 // While SQLite Mutexes may be recursive, in our own code we do not want to 61 // treat them as such. 62 CheckAcquire(); 63 #endif 64 65 ::sqlite3_mutex_enter(mMutex); 66 67 #if defined(DEBUG) 68 Acquire(); // Call is protected by us holding the mutex. 69 #endif 70 } 71 72 /** 73 * Releases the mutex. 74 */ 75 void unlock() { 76 MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); 77 #if defined(DEBUG) 78 // While SQLite Mutexes may be recursive, in our own code we do not want to 79 // treat them as such. 80 Release(); // Call is protected by us holding the mutex. 81 #endif 82 83 ::sqlite3_mutex_leave(mMutex); 84 } 85 86 /** 87 * Asserts that the current thread owns the mutex. 88 */ 89 void assertCurrentThreadOwns() { 90 MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); 91 MOZ_ASSERT(::sqlite3_mutex_held(mMutex), 92 "Mutex is not held, but we expect it to be!"); 93 } 94 95 /** 96 * Asserts that the current thread does not own the mutex. 97 */ 98 void assertNotCurrentThreadOwns() { 99 MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); 100 MOZ_ASSERT(::sqlite3_mutex_notheld(mMutex), 101 "Mutex is held, but we expect it to not be!"); 102 } 103 104 private: 105 sqlite3_mutex* mMutex; 106 }; 107 108 /** 109 * Automatically acquires the mutex when it enters scope, and releases it when 110 * it leaves scope. 111 */ 112 class MOZ_STACK_CLASS SQLiteMutexAutoLock { 113 public: 114 explicit SQLiteMutexAutoLock(SQLiteMutex& aMutex) : mMutex(aMutex) { 115 mMutex.lock(); 116 } 117 118 ~SQLiteMutexAutoLock() { mMutex.unlock(); } 119 120 private: 121 SQLiteMutex& mMutex; 122 }; 123 124 /** 125 * Automatically releases the mutex when it enters scope, and acquires it when 126 * it leaves scope. 127 */ 128 class MOZ_STACK_CLASS SQLiteMutexAutoUnlock { 129 public: 130 explicit SQLiteMutexAutoUnlock(SQLiteMutex& aMutex) : mMutex(aMutex) { 131 mMutex.unlock(); 132 } 133 134 ~SQLiteMutexAutoUnlock() { mMutex.lock(); } 135 136 private: 137 SQLiteMutex& mMutex; 138 }; 139 140 } // namespace storage 141 } // namespace mozilla 142 143 #endif // mozilla_storage_SQLiteMutex_h_