|
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 { |
|
25 public: |
|
26 /** |
|
27 * Constructs a wrapper for a sqlite3_mutex that has deadlock detecting. |
|
28 * |
|
29 * @param aName |
|
30 * A name which can be used to reference this mutex. |
|
31 */ |
|
32 SQLiteMutex(const char *aName) |
|
33 : BlockingResourceBase(aName, eMutex) |
|
34 , mMutex(nullptr) |
|
35 { |
|
36 } |
|
37 |
|
38 /** |
|
39 * Sets the mutex that we are wrapping. We generally do not have access to |
|
40 * our mutex at class construction, so we have to set it once we get access to |
|
41 * it. |
|
42 * |
|
43 * @param aMutex |
|
44 * The sqlite3_mutex that we are going to wrap. |
|
45 */ |
|
46 void initWithMutex(sqlite3_mutex *aMutex) |
|
47 { |
|
48 NS_ASSERTION(aMutex, "You must pass in a valid mutex!"); |
|
49 NS_ASSERTION(!mMutex, "A mutex has already been set for this!"); |
|
50 mMutex = aMutex; |
|
51 } |
|
52 |
|
53 #if !defined(DEBUG) || defined(MOZ_NATIVE_SQLITE) |
|
54 /** |
|
55 * Acquires the mutex. |
|
56 */ |
|
57 void lock() |
|
58 { |
|
59 sqlite3_mutex_enter(mMutex); |
|
60 } |
|
61 |
|
62 /** |
|
63 * Releases the mutex. |
|
64 */ |
|
65 void unlock() |
|
66 { |
|
67 sqlite3_mutex_leave(mMutex); |
|
68 } |
|
69 |
|
70 /** |
|
71 * Asserts that the current thread owns the mutex. |
|
72 */ |
|
73 void assertCurrentThreadOwns() |
|
74 { |
|
75 } |
|
76 |
|
77 /** |
|
78 * Asserts that the current thread does not own the mutex. |
|
79 */ |
|
80 void assertNotCurrentThreadOwns() |
|
81 { |
|
82 } |
|
83 |
|
84 #else |
|
85 void lock() |
|
86 { |
|
87 NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); |
|
88 |
|
89 // While SQLite Mutexes may be recursive, in our own code we do not want to |
|
90 // treat them as such. |
|
91 CallStack callContext = CallStack(); |
|
92 |
|
93 CheckAcquire(callContext); |
|
94 sqlite3_mutex_enter(mMutex); |
|
95 Acquire(callContext); // Call is protected by us holding the mutex. |
|
96 } |
|
97 |
|
98 void unlock() |
|
99 { |
|
100 NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); |
|
101 |
|
102 // While SQLite Mutexes may be recursive, in our own code we do not want to |
|
103 // treat them as such. |
|
104 Release(); // Call is protected by us holding the mutex. |
|
105 sqlite3_mutex_leave(mMutex); |
|
106 } |
|
107 |
|
108 void assertCurrentThreadOwns() |
|
109 { |
|
110 NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); |
|
111 NS_ASSERTION(sqlite3_mutex_held(mMutex), |
|
112 "Mutex is not held, but we expect it to be!"); |
|
113 } |
|
114 |
|
115 void assertNotCurrentThreadOwns() |
|
116 { |
|
117 NS_ASSERTION(mMutex, "No mutex associated with this wrapper!"); |
|
118 NS_ASSERTION(sqlite3_mutex_notheld(mMutex), |
|
119 "Mutex is held, but we expect it to not be!"); |
|
120 } |
|
121 #endif // ifndef DEBUG |
|
122 |
|
123 private: |
|
124 sqlite3_mutex *mMutex; |
|
125 }; |
|
126 |
|
127 /** |
|
128 * Automatically acquires the mutex when it enters scope, and releases it when |
|
129 * it leaves scope. |
|
130 */ |
|
131 class MOZ_STACK_CLASS SQLiteMutexAutoLock |
|
132 { |
|
133 public: |
|
134 SQLiteMutexAutoLock(SQLiteMutex &aMutex) |
|
135 : mMutex(aMutex) |
|
136 { |
|
137 mMutex.lock(); |
|
138 } |
|
139 |
|
140 ~SQLiteMutexAutoLock() |
|
141 { |
|
142 mMutex.unlock(); |
|
143 } |
|
144 |
|
145 private: |
|
146 SQLiteMutex &mMutex; |
|
147 }; |
|
148 |
|
149 /** |
|
150 * Automatically releases the mutex when it enters scope, and acquires it when |
|
151 * it leaves scope. |
|
152 */ |
|
153 class MOZ_STACK_CLASS SQLiteMutexAutoUnlock |
|
154 { |
|
155 public: |
|
156 SQLiteMutexAutoUnlock(SQLiteMutex &aMutex) |
|
157 : mMutex(aMutex) |
|
158 { |
|
159 mMutex.unlock(); |
|
160 } |
|
161 |
|
162 ~SQLiteMutexAutoUnlock() |
|
163 { |
|
164 mMutex.lock(); |
|
165 } |
|
166 |
|
167 private: |
|
168 SQLiteMutex &mMutex; |
|
169 }; |
|
170 |
|
171 } // namespace storage |
|
172 } // namespace mozilla |
|
173 |
|
174 #endif // mozilla_storage_SQLiteMutex_h_ |