/src/mozilla-central/storage/SQLiteMutex.h
Line | Count | Source (jump to first uncovered line) |
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 | | explicit SQLiteMutex(const char *aName) |
33 | | : BlockingResourceBase(aName, eMutex) |
34 | | , mMutex(nullptr) |
35 | 0 | { |
36 | 0 | } |
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 | 0 | { |
48 | 0 | NS_ASSERTION(aMutex, "You must pass in a valid mutex!"); |
49 | 0 | NS_ASSERTION(!mMutex, "A mutex has already been set for this!"); |
50 | 0 | mMutex = aMutex; |
51 | 0 | } |
52 | | |
53 | | /** |
54 | | * After a connection has been successfully closed, its mutex is a dangling |
55 | | * pointer, and as such it should be destroyed. |
56 | | */ |
57 | 0 | void destroy() { |
58 | 0 | mMutex = NULL; |
59 | 0 | } |
60 | | |
61 | | #if !defined(DEBUG) || defined(MOZ_SYSTEM_SQLITE) |
62 | | /** |
63 | | * Acquires the mutex. |
64 | | */ |
65 | | void lock() |
66 | 0 | { |
67 | 0 | ::sqlite3_mutex_enter(mMutex); |
68 | 0 | } |
69 | | |
70 | | /** |
71 | | * Releases the mutex. |
72 | | */ |
73 | | void unlock() |
74 | 0 | { |
75 | 0 | ::sqlite3_mutex_leave(mMutex); |
76 | 0 | } |
77 | | |
78 | | /** |
79 | | * Asserts that the current thread owns the mutex. |
80 | | */ |
81 | | void assertCurrentThreadOwns() |
82 | 0 | { |
83 | 0 | } |
84 | | |
85 | | /** |
86 | | * Asserts that the current thread does not own the mutex. |
87 | | */ |
88 | | void assertNotCurrentThreadOwns() |
89 | 0 | { |
90 | 0 | } |
91 | | |
92 | | #else |
93 | | void lock() |
94 | | { |
95 | | MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); |
96 | | |
97 | | // While SQLite Mutexes may be recursive, in our own code we do not want to |
98 | | // treat them as such. |
99 | | |
100 | | CheckAcquire(); |
101 | | ::sqlite3_mutex_enter(mMutex); |
102 | | Acquire(); // Call is protected by us holding the mutex. |
103 | | } |
104 | | |
105 | | void unlock() |
106 | | { |
107 | | MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); |
108 | | |
109 | | // While SQLite Mutexes may be recursive, in our own code we do not want to |
110 | | // treat them as such. |
111 | | Release(); // Call is protected by us holding the mutex. |
112 | | ::sqlite3_mutex_leave(mMutex); |
113 | | } |
114 | | |
115 | | void assertCurrentThreadOwns() |
116 | | { |
117 | | MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); |
118 | | MOZ_ASSERT(sqlite3_mutex_held(mMutex), |
119 | | "Mutex is not held, but we expect it to be!"); |
120 | | } |
121 | | |
122 | | void assertNotCurrentThreadOwns() |
123 | | { |
124 | | MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!"); |
125 | | MOZ_ASSERT(sqlite3_mutex_notheld(mMutex), |
126 | | "Mutex is held, but we expect it to not be!"); |
127 | | } |
128 | | #endif // ifndef DEBUG |
129 | | |
130 | | private: |
131 | | sqlite3_mutex *mMutex; |
132 | | }; |
133 | | |
134 | | /** |
135 | | * Automatically acquires the mutex when it enters scope, and releases it when |
136 | | * it leaves scope. |
137 | | */ |
138 | | class MOZ_STACK_CLASS SQLiteMutexAutoLock |
139 | | { |
140 | | public: |
141 | | explicit SQLiteMutexAutoLock(SQLiteMutex &aMutex) |
142 | | : mMutex(aMutex) |
143 | 0 | { |
144 | 0 | mMutex.lock(); |
145 | 0 | } |
146 | | |
147 | | ~SQLiteMutexAutoLock() |
148 | 0 | { |
149 | 0 | mMutex.unlock(); |
150 | 0 | } |
151 | | |
152 | | private: |
153 | | SQLiteMutex &mMutex; |
154 | | }; |
155 | | |
156 | | /** |
157 | | * Automatically releases the mutex when it enters scope, and acquires it when |
158 | | * it leaves scope. |
159 | | */ |
160 | | class MOZ_STACK_CLASS SQLiteMutexAutoUnlock |
161 | | { |
162 | | public: |
163 | | explicit SQLiteMutexAutoUnlock(SQLiteMutex &aMutex) |
164 | | : mMutex(aMutex) |
165 | 0 | { |
166 | 0 | mMutex.unlock(); |
167 | 0 | } |
168 | | |
169 | | ~SQLiteMutexAutoUnlock() |
170 | 0 | { |
171 | 0 | mMutex.lock(); |
172 | 0 | } |
173 | | |
174 | | private: |
175 | | SQLiteMutex &mMutex; |
176 | | }; |
177 | | |
178 | | } // namespace storage |
179 | | } // namespace mozilla |
180 | | |
181 | | #endif // mozilla_storage_SQLiteMutex_h_ |