FileInfoManager.h (4603B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 DOM_INDEXEDDB_FILEINFOMANAGER_H_ 8 #define DOM_INDEXEDDB_FILEINFOMANAGER_H_ 9 10 #include "FileInfo.h" 11 #include "FlippedOnce.h" 12 #include "mozilla/Mutex.h" 13 #include "mozilla/StaticMutex.h" 14 #include "nsHashKeys.h" 15 #include "nsISupportsImpl.h" 16 #include "nsTHashMap.h" 17 18 namespace mozilla::dom::indexedDB { 19 20 class FileInfoManagerBase { 21 public: 22 bool Invalidated() const { return mInvalidated; } 23 24 protected: 25 bool AssertValid() const { 26 if (NS_WARN_IF(Invalidated())) { 27 MOZ_ASSERT(false); 28 return false; 29 } 30 31 return true; 32 } 33 34 void Invalidate() { mInvalidated.Flip(); } 35 36 private: 37 FlippedOnce<false> mInvalidated; 38 }; 39 40 template <typename FileManager> 41 class FileInfoManager : public FileInfoManagerBase { 42 public: 43 using FileInfoType = FileInfo<FileManager>; 44 using MutexType = StaticMutex; 45 using AutoLockType = mozilla::detail::BaseAutoLock<MutexType&>; 46 47 [[nodiscard]] SafeRefPtr<FileInfoType> GetFileInfo(int64_t aId) const { 48 return AcquireFileInfo([this, aId]() MOZ_REQUIRES(Mutex()) { 49 return mFileInfos.MaybeGet(aId); 50 }); 51 } 52 53 bool ContainsFileInfo(int64_t aFileId) { 54 AutoLockType lock(Mutex()); 55 return mFileInfos.Contains(aFileId); 56 } 57 58 [[nodiscard]] SafeRefPtr<FileInfoType> CreateFileInfo( 59 const Maybe<int64_t>& aMaybeId = Nothing(), 60 const nsrefcnt aDBRefCnt = 0) { 61 return AcquireFileInfo([this, &aMaybeId, 62 &aDBRefCnt]() MOZ_REQUIRES(Mutex()) { 63 const int64_t id = aMaybeId.isSome() ? *aMaybeId : ++mLastFileId; 64 65 auto fileInfo = 66 MakeNotNull<FileInfoType*>(FileInfoManagerGuard{}, 67 SafeRefPtr{static_cast<FileManager*>(this), 68 AcquireStrongRefFromRawPtr{}}, 69 id, aDBRefCnt); 70 71 mFileInfos.InsertOrUpdate(id, fileInfo); 72 73 if (aMaybeId.isSome()) { 74 mLastFileId = std::max(id, mLastFileId); 75 } 76 77 return Some(fileInfo); 78 }); 79 } 80 81 void RemoveFileInfo(const int64_t aId, const AutoLockType& aFileMutexLock) 82 MOZ_REQUIRES(Mutex()) { 83 #ifdef DEBUG 84 aFileMutexLock.AssertOwns(Mutex()); 85 #endif 86 mFileInfos.Remove(aId); 87 } 88 89 // After calling this method, callers should not call any more methods on this 90 // class. 91 virtual nsresult Invalidate() { 92 AutoLockType lock(Mutex()); 93 94 FileInfoManagerBase::Invalidate(); 95 96 mFileInfos.RemoveIf([](const auto& iter) { 97 FileInfoType* info = iter.Data(); 98 MOZ_ASSERT(info); 99 100 return !info->LockedClearDBRefs(FileInfoManagerGuard{}); 101 }); 102 103 return NS_OK; 104 } 105 106 struct FileInfoManagerGuard { 107 FileInfoManagerGuard() = default; 108 }; 109 110 static MutexType& Mutex() { return FileManager::MutexInstance(); } 111 112 private: 113 // Runs the given aFileInfoTableOp operation, which must return a FileInfo*, 114 // under the FileManager lock, acquires a strong reference to the returned 115 // object under the lock, and returns the strong reference. 116 template <typename FileInfoTableOp> 117 [[nodiscard]] SafeRefPtr<FileInfoType> AcquireFileInfo( 118 const FileInfoTableOp& aFileInfoTableOp) const { 119 if (!AssertValid()) { 120 // In release, the assertions are disabled. 121 return nullptr; 122 } 123 124 // We cannot simply change this to SafeRefPtr<FileInfo>, because 125 // FileInfo::AddRef also acquires the FileManager::Mutex. 126 auto fileInfo = [&aFileInfoTableOp]() -> RefPtr<FileInfoType> { 127 AutoLockType lock(Mutex()); 128 129 const auto maybeFileInfo = aFileInfoTableOp(); 130 if (maybeFileInfo) { 131 const auto& fileInfo = maybeFileInfo.ref(); 132 fileInfo->LockedAddRef(); 133 return dont_AddRef(fileInfo.get()); 134 } 135 136 return {}; 137 }(); 138 139 return SafeRefPtr{std::move(fileInfo)}; 140 } 141 142 // Access to the following private fields must be protected by 143 // FileManager::Mutex() which is now enforced by MOZ_GUARDED_BY annotations. 144 nsTHashMap<nsUint64HashKey, NotNull<FileInfoType*>> mFileInfos 145 MOZ_GUARDED_BY(Mutex()); 146 147 int64_t mLastFileId MOZ_GUARDED_BY(Mutex()) = 0; 148 149 protected: 150 #ifdef DEBUG 151 ~FileInfoManager() { MOZ_ASSERT(mFileInfos.IsEmpty()); } 152 #else 153 ~FileInfoManager() = default; 154 #endif 155 }; 156 157 } // namespace mozilla::dom::indexedDB 158 159 #endif // DOM_INDEXEDDB_FILEINFOMANAGER_H_