1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/src/SQLiteMutex.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,174 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_storage_SQLiteMutex_h_ 1.11 +#define mozilla_storage_SQLiteMutex_h_ 1.12 + 1.13 +#include "mozilla/BlockingResourceBase.h" 1.14 +#include "sqlite3.h" 1.15 + 1.16 +namespace mozilla { 1.17 +namespace storage { 1.18 + 1.19 +/** 1.20 + * Wrapper class for sqlite3_mutexes. To be used whenever we want to use a 1.21 + * sqlite3_mutex. 1.22 + * 1.23 + * @warning Never EVER wrap the same sqlite3_mutex with a different SQLiteMutex. 1.24 + * If you do this, you void the deadlock detector's warranty! 1.25 + */ 1.26 +class SQLiteMutex : private BlockingResourceBase 1.27 +{ 1.28 +public: 1.29 + /** 1.30 + * Constructs a wrapper for a sqlite3_mutex that has deadlock detecting. 1.31 + * 1.32 + * @param aName 1.33 + * A name which can be used to reference this mutex. 1.34 + */ 1.35 + SQLiteMutex(const char *aName) 1.36 + : BlockingResourceBase(aName, eMutex) 1.37 + , mMutex(nullptr) 1.38 + { 1.39 + } 1.40 + 1.41 + /** 1.42 + * Sets the mutex that we are wrapping. We generally do not have access to 1.43 + * our mutex at class construction, so we have to set it once we get access to 1.44 + * it. 1.45 + * 1.46 + * @param aMutex 1.47 + * The sqlite3_mutex that we are going to wrap. 1.48 + */ 1.49 + void initWithMutex(sqlite3_mutex *aMutex) 1.50 + { 1.51 + NS_ASSERTION(aMutex, "You must pass in a valid mutex!"); 1.52 + NS_ASSERTION(!mMutex, "A mutex has already been set for this!"); 1.53 + mMutex = aMutex; 1.54 + } 1.55 + 1.56 +#if !defined(DEBUG) || defined(MOZ_NATIVE_SQLITE) 1.57 + /** 1.58 + * Acquires the mutex. 1.59 + */ 1.60 + void lock() 1.61 + { 1.62 + sqlite3_mutex_enter(mMutex); 1.63 + } 1.64 + 1.65 + /** 1.66 + * Releases the mutex. 1.67 + */ 1.68 + void unlock() 1.69 + { 1.70 + sqlite3_mutex_leave(mMutex); 1.71 + } 1.72 + 1.73 + /** 1.74 + * Asserts that the current thread owns the mutex. 1.75 + */ 1.76 + void assertCurrentThreadOwns() 1.77 + { 1.78 + } 1.79 + 1.80 + /** 1.81 + * Asserts that the current thread does not own the mutex. 1.82 + */ 1.83 + void assertNotCurrentThreadOwns() 1.84 + { 1.85 + } 1.86 + 1.87 +#else 1.88 + void lock() 1.89 + { 1.90 + NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); 1.91 + 1.92 + // While SQLite Mutexes may be recursive, in our own code we do not want to 1.93 + // treat them as such. 1.94 + CallStack callContext = CallStack(); 1.95 + 1.96 + CheckAcquire(callContext); 1.97 + sqlite3_mutex_enter(mMutex); 1.98 + Acquire(callContext); // Call is protected by us holding the mutex. 1.99 + } 1.100 + 1.101 + void unlock() 1.102 + { 1.103 + NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); 1.104 + 1.105 + // While SQLite Mutexes may be recursive, in our own code we do not want to 1.106 + // treat them as such. 1.107 + Release(); // Call is protected by us holding the mutex. 1.108 + sqlite3_mutex_leave(mMutex); 1.109 + } 1.110 + 1.111 + void assertCurrentThreadOwns() 1.112 + { 1.113 + NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); 1.114 + NS_ASSERTION(sqlite3_mutex_held(mMutex), 1.115 + "Mutex is not held, but we expect it to be!"); 1.116 + } 1.117 + 1.118 + void assertNotCurrentThreadOwns() 1.119 + { 1.120 + NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); 1.121 + NS_ASSERTION(sqlite3_mutex_notheld(mMutex), 1.122 + "Mutex is held, but we expect it to not be!"); 1.123 + } 1.124 +#endif // ifndef DEBUG 1.125 + 1.126 +private: 1.127 + sqlite3_mutex *mMutex; 1.128 +}; 1.129 + 1.130 +/** 1.131 + * Automatically acquires the mutex when it enters scope, and releases it when 1.132 + * it leaves scope. 1.133 + */ 1.134 +class MOZ_STACK_CLASS SQLiteMutexAutoLock 1.135 +{ 1.136 +public: 1.137 + SQLiteMutexAutoLock(SQLiteMutex &aMutex) 1.138 + : mMutex(aMutex) 1.139 + { 1.140 + mMutex.lock(); 1.141 + } 1.142 + 1.143 + ~SQLiteMutexAutoLock() 1.144 + { 1.145 + mMutex.unlock(); 1.146 + } 1.147 + 1.148 +private: 1.149 + SQLiteMutex &mMutex; 1.150 +}; 1.151 + 1.152 +/** 1.153 + * Automatically releases the mutex when it enters scope, and acquires it when 1.154 + * it leaves scope. 1.155 + */ 1.156 +class MOZ_STACK_CLASS SQLiteMutexAutoUnlock 1.157 +{ 1.158 +public: 1.159 + SQLiteMutexAutoUnlock(SQLiteMutex &aMutex) 1.160 + : mMutex(aMutex) 1.161 + { 1.162 + mMutex.unlock(); 1.163 + } 1.164 + 1.165 + ~SQLiteMutexAutoUnlock() 1.166 + { 1.167 + mMutex.lock(); 1.168 + } 1.169 + 1.170 +private: 1.171 + SQLiteMutex &mMutex; 1.172 +}; 1.173 + 1.174 +} // namespace storage 1.175 +} // namespace mozilla 1.176 + 1.177 +#endif // mozilla_storage_SQLiteMutex_h_