Line data Source code
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 1 : 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 8 : explicit SQLiteMutex(const char *aName)
33 8 : : BlockingResourceBase(aName, eMutex)
34 8 : , mMutex(nullptr)
35 : {
36 8 : }
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 8 : void initWithMutex(sqlite3_mutex *aMutex)
47 : {
48 8 : NS_ASSERTION(aMutex, "You must pass in a valid mutex!");
49 8 : NS_ASSERTION(!mMutex, "A mutex has already been set for this!");
50 8 : mMutex = aMutex;
51 8 : }
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 1 : void destroy() {
58 1 : mMutex = NULL;
59 1 : }
60 :
61 : #if !defined(DEBUG) || defined(MOZ_SYSTEM_SQLITE)
62 : /**
63 : * Acquires the mutex.
64 : */
65 : void lock()
66 : {
67 : ::sqlite3_mutex_enter(mMutex);
68 : }
69 :
70 : /**
71 : * Releases the mutex.
72 : */
73 : void unlock()
74 : {
75 : ::sqlite3_mutex_leave(mMutex);
76 : }
77 :
78 : /**
79 : * Asserts that the current thread owns the mutex.
80 : */
81 : void assertCurrentThreadOwns()
82 : {
83 : }
84 :
85 : /**
86 : * Asserts that the current thread does not own the mutex.
87 : */
88 : void assertNotCurrentThreadOwns()
89 : {
90 : }
91 :
92 : #else
93 44 : void lock()
94 : {
95 44 : 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 44 : CheckAcquire();
101 44 : ::sqlite3_mutex_enter(mMutex);
102 44 : Acquire(); // Call is protected by us holding the mutex.
103 44 : }
104 :
105 44 : void unlock()
106 : {
107 44 : 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 44 : Release(); // Call is protected by us holding the mutex.
112 44 : ::sqlite3_mutex_leave(mMutex);
113 44 : }
114 :
115 0 : void assertCurrentThreadOwns()
116 : {
117 0 : MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!");
118 0 : MOZ_ASSERT(sqlite3_mutex_held(mMutex),
119 : "Mutex is not held, but we expect it to be!");
120 0 : }
121 :
122 0 : void assertNotCurrentThreadOwns()
123 : {
124 0 : MOZ_ASSERT(mMutex, "No mutex associated with this wrapper!");
125 0 : MOZ_ASSERT(sqlite3_mutex_notheld(mMutex),
126 : "Mutex is held, but we expect it to not be!");
127 0 : }
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 44 : explicit SQLiteMutexAutoLock(SQLiteMutex &aMutex)
142 44 : : mMutex(aMutex)
143 : {
144 44 : mMutex.lock();
145 44 : }
146 :
147 44 : ~SQLiteMutexAutoLock()
148 44 : {
149 44 : mMutex.unlock();
150 44 : }
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 0 : explicit SQLiteMutexAutoUnlock(SQLiteMutex &aMutex)
164 0 : : mMutex(aMutex)
165 : {
166 0 : mMutex.unlock();
167 0 : }
168 :
169 0 : ~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_
|