/* -*- 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 DOM_FS_SHARED_FILESYSTEMHELPERS_H_ #define DOM_FS_SHARED_FILESYSTEMHELPERS_H_ #include "FileSystemTypes.h" #include "mozilla/RefPtr.h" namespace mozilla::dom::fs { // XXX Consider moving this class template to MFBT. // A wrapper class template on top of the RefPtr. The RefPtr provides us the // automatic reference counting of objects with AddRef() and Release() methods. // `Registered` provides automatic registration counting of objects with // Register() and Unregister() methods. Registration counting works similarly // as reference counting, but objects are not deleted when the number of // registrations drops to zero (that's managed by reference counting). Instead, // an object can trigger an asynchronous close operation which still needs to // hold and use the referenced object. Example: // // using BoolPromise = MozPromise; // // class MyObject { // public: // NS_INLINE_DECL_REFCOUNTING(MyObject) // // void Register() { // mRegCnt++; // } // // void Unregister() { // mRegCnt--; // if (mRegCnt == 0) { // BeginClose(); // } // } // // private: // RefPtr BeginClose() { // return InvokeAsync(mIOTaskQueue, __func__, // []() { // return BoolPromise::CreateAndResolve(true, __func__); // }) // ->Then(GetCurrentSerialEventTarget(), __func__, // [self = RefPtr(this)]( // const BoolPromise::ResolveOrRejectValue&) { // return self->mIOTaskQueue->BeginShutdown(); // }) // ->Then(GetCurrentSerialEventTarget(), __func__, // [self = RefPtr(this)]( // const ShutdownPromise::ResolveOrRejectValue&) { // return BoolPromise::CreateAndResolve(true, __func__); // }); // } // // RefPtr mIOTaskQueue; // uint32_t mRegCnt = 0; // }; template class Registered { private: RefPtr mObject; public: ~Registered() { if (mObject) { mObject->Unregister(); } } Registered() = default; Registered(const Registered& aOther) : mObject(aOther.mObject) { mObject->Register(); } Registered(Registered&& aOther) noexcept = default; MOZ_IMPLICIT Registered(RefPtr aObject) : mObject(std::move(aObject)) { if (mObject) { mObject->Register(); } } Registered& operator=(decltype(nullptr)) { RefPtr oldObject = std::move(mObject); mObject = nullptr; if (oldObject) { oldObject->Unregister(); } return *this; } Registered& operator=(const Registered& aRhs) { if (aRhs.mObject) { aRhs.mObject->Register(); } RefPtr oldObject = std::move(mObject); mObject = aRhs.mObject; if (oldObject) { oldObject->Unregister(); } return *this; } Registered& operator=(Registered&& aRhs) noexcept { RefPtr oldObject = std::move(mObject); mObject = std::move(aRhs.mObject); aRhs.mObject = nullptr; if (oldObject) { oldObject->Unregister(); } return *this; } const RefPtr& inspect() const { return mObject; } RefPtr unwrap() { RefPtr oldObject = std::move(mObject); mObject = nullptr; if (oldObject) { oldObject->Unregister(); } return oldObject; } T* get() const { return mObject; } operator T*() const& { return get(); } T* operator->() const { return get(); } }; // Spec says valid names don't include (os-dependent) path separators, // and is not equal to a dot . or two dots .. // We want to use the same validator from both child and parent. bool IsValidName(const fs::Name& aName); } // namespace mozilla::dom::fs #endif // DOM_FS_SHARED_FILESYSTEMHELPERS_H_