ClientDirectoryLockHandle.cpp (4326B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/quota/ClientDirectoryLockHandle.h" 8 9 #include "mozilla/dom/quota/ClientDirectoryLock.h" 10 #include "mozilla/dom/quota/DirectoryLock.h" 11 #include "mozilla/dom/quota/DirectoryLockInlines.h" 12 #include "mozilla/dom/quota/QuotaManager.h" 13 14 namespace mozilla::dom::quota { 15 16 ClientDirectoryLockHandle::ClientDirectoryLockHandle() { 17 MOZ_COUNT_CTOR(mozilla::dom::quota::ClientDirectoryLockHandle); 18 } 19 20 ClientDirectoryLockHandle::ClientDirectoryLockHandle( 21 RefPtr<ClientDirectoryLock> aClientDirectoryLock) { 22 aClientDirectoryLock->AssertIsOnOwningThread(); 23 24 mClientDirectoryLock = std::move(aClientDirectoryLock); 25 26 MOZ_COUNT_CTOR(mozilla::dom::quota::ClientDirectoryLockHandle); 27 } 28 29 ClientDirectoryLockHandle::ClientDirectoryLockHandle( 30 ClientDirectoryLockHandle&& aOther) noexcept { 31 aOther.AssertIsOnOwningThread(); 32 33 mClientDirectoryLock = std::move(aOther.mClientDirectoryLock); 34 35 // Explicitly null aOther.mClientDirectoryLock so that aOther appears inert 36 // immediately after the move. While RefPtr nulls out its mRawPtr internally, 37 // the store may be reordered in optimized builds, possibly occurring only 38 // just before RefPtr’s own destructor runs. Without this, the moved-from 39 // handle’s destructor may observe a stale non-null value. 40 aOther.mClientDirectoryLock = nullptr; 41 42 mRegistered = std::exchange(aOther.mRegistered, false); 43 44 MOZ_COUNT_CTOR(mozilla::dom::quota::ClientDirectoryLockHandle); 45 } 46 47 ClientDirectoryLockHandle::~ClientDirectoryLockHandle() { 48 // If mClientDirectoryLock is null, this handle is in an inert state — either 49 // it was default-constructed or moved. 50 // 51 // This check is safe here because destruction implies no other thread is 52 // using the handle. Any use-after-destroy bugs would indicate a much more 53 // serious issue (e.g., a dangling pointer), and should be caught by tools 54 // like AddressSanitizer. 55 if (mClientDirectoryLock) { 56 AssertIsOnOwningThread(); 57 58 mClientDirectoryLock->MutableManagerRef().ClientDirectoryLockHandleDestroy( 59 *this); 60 61 DropDirectoryLock(mClientDirectoryLock); 62 } 63 64 MOZ_COUNT_DTOR(mozilla::dom::quota::ClientDirectoryLockHandle); 65 } 66 67 void ClientDirectoryLockHandle::AssertIsOnOwningThread() const { 68 NS_ASSERT_OWNINGTHREAD(ClientDirectoryLockHandle); 69 } 70 71 ClientDirectoryLockHandle& ClientDirectoryLockHandle::operator=( 72 ClientDirectoryLockHandle&& aOther) noexcept { 73 AssertIsOnOwningThread(); 74 aOther.AssertIsOnOwningThread(); 75 76 if (this != &aOther) { 77 mClientDirectoryLock = std::move(aOther.mClientDirectoryLock); 78 79 // Explicitly null aOther.mClientDirectoryLock so that aOther appears inert 80 // immediately after the move. While RefPtr nulls out its mRawPtr 81 // internally, the store may be reordered in optimized builds, possibly 82 // occurring only just before RefPtr’s own destructor runs. Without this, 83 // the moved-from handle’s destructor may observe a stale non-null value. 84 aOther.mClientDirectoryLock = nullptr; 85 86 mRegistered = std::exchange(aOther.mRegistered, false); 87 } 88 89 return *this; 90 } 91 92 ClientDirectoryLockHandle::operator bool() const { 93 AssertIsOnOwningThread(); 94 95 return !!mClientDirectoryLock; 96 } 97 98 ClientDirectoryLock* ClientDirectoryLockHandle::get() const { 99 AssertIsOnOwningThread(); 100 101 return mClientDirectoryLock ? mClientDirectoryLock.get() : nullptr; 102 } 103 104 ClientDirectoryLock& ClientDirectoryLockHandle::operator*() const { 105 AssertIsOnOwningThread(); 106 107 return *get(); 108 } 109 110 ClientDirectoryLock* ClientDirectoryLockHandle::operator->() const { 111 AssertIsOnOwningThread(); 112 113 return get(); 114 } 115 116 bool ClientDirectoryLockHandle::IsRegistered() const { 117 AssertIsOnOwningThread(); 118 119 return mRegistered; 120 } 121 122 void ClientDirectoryLockHandle::SetRegistered(bool aRegistered) { 123 AssertIsOnOwningThread(); 124 125 mRegistered = aRegistered; 126 } 127 128 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED 129 130 bool ClientDirectoryLockHandle::IsInert() const { 131 return !mClientDirectoryLock; 132 } 133 134 #endif 135 136 } // namespace mozilla::dom::quota