storage/src/SQLiteMutex.h

changeset 0
6474c204b198
     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_

mercurial