DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (cdf352f02ac4)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_indexeddb_filemanagerbase_h__
#define mozilla_dom_indexeddb_filemanagerbase_h__

#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "mozilla/StaticMutex.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsISupportsImpl.h"
#include "FileInfoT.h"
#include "FlippedOnce.h"

namespace mozilla {
namespace dom {
namespace indexedDB {

template <typename FileManager>
class FileManagerBase {
 public:
  using FileInfo = FileInfoT<FileManager>;
  using MutexType = StaticMutex;
  using AutoLock = mozilla::detail::BaseAutoLock<MutexType&>;

  MOZ_MUST_USE SafeRefPtr<FileInfo> GetFileInfo(int64_t aId) const {
    if (!AssertValid()) {
      // In release, the assertions are disabled.
      return nullptr;
    }

    // TODO: We cannot simply change this to SafeRefPtr<FileInfo>, because
    // FileInfo::AddRef also acquires the FileManager::Mutex.
    // This looks quirky at least.
    FileInfo* fileInfo;
    {
      AutoLock lock(FileManager::Mutex());
      fileInfo = mFileInfos.Get(aId);
    }

    return {fileInfo, AcquireStrongRefFromRawPtr{}};
  }

  MOZ_MUST_USE SafeRefPtr<FileInfo> CreateFileInfo() {
    if (!AssertValid()) {
      // In release, the assertions are disabled.
      return nullptr;
    }

    // TODO: We cannot simply change this to SafeRefPtr<FileInfo>, because
    // FileInfo::AddRef also acquires the FileManager::Mutex.
    // This looks quirky at least.
    FileInfo* fileInfo;
    {
      AutoLock lock(FileManager::Mutex());

      const int64_t id = ++mLastFileId;

      fileInfo = new FileInfo(FileManagerGuard{},
                              SafeRefPtr{static_cast<FileManager*>(this),
                                         AcquireStrongRefFromRawPtr{}},
                              id);

      mFileInfos.Put(id, fileInfo);
    }

    return {fileInfo, AcquireStrongRefFromRawPtr{}};
  }

  void RemoveFileInfo(const int64_t aId, const AutoLock& aFileMutexLock) {
#ifdef DEBUG
    aFileMutexLock.AssertOwns(FileManager::Mutex());
#endif
    mFileInfos.Remove(aId);
  }

  nsresult Invalidate() {
    AutoLock lock(FileManager::Mutex());

    mInvalidated.Flip();

    mFileInfos.RemoveIf([](const auto& iter) {
      FileInfo* info = iter.Data();
      MOZ_ASSERT(info);

      return !info->LockedClearDBRefs(FileManagerGuard{});
    });

    return NS_OK;
  }

  bool Invalidated() const { return mInvalidated; }

  class FileManagerGuard {
    FileManagerGuard() = default;
  };

 protected:
  bool AssertValid() const {
    if (NS_WARN_IF(static_cast<const FileManager*>(this)->Invalidated())) {
      MOZ_ASSERT(false);
      return false;
    }

    return true;
  }

#ifdef DEBUG
  ~FileManagerBase() { MOZ_ASSERT(mFileInfos.IsEmpty()); }
#else
  ~FileManagerBase() = default;
#endif

  // Access to the following fields must be protected by
  // FileManager::Mutex()
  int64_t mLastFileId = 0;
  nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;

  FlippedOnce<false> mInvalidated;
};

}  // namespace indexedDB
}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_indexeddb_filemanagerbase_h__