summaryrefslogtreecommitdiffstats
path: root/dom/fs/shared/FileSystemHelpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/fs/shared/FileSystemHelpers.h')
-rw-r--r--dom/fs/shared/FileSystemHelpers.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/dom/fs/shared/FileSystemHelpers.h b/dom/fs/shared/FileSystemHelpers.h
new file mode 100644
index 0000000000..26a820f343
--- /dev/null
+++ b/dom/fs/shared/FileSystemHelpers.h
@@ -0,0 +1,147 @@
+/* -*- 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<bool, nsresult, false>;
+//
+// class MyObject {
+// public:
+// NS_INLINE_DECL_REFCOUNTING(MyObject)
+//
+// void Register() {
+// mRegCnt++;
+// }
+//
+// void Unregister() {
+// mRegCnt--;
+// if (mRegCnt == 0) {
+// BeginClose();
+// }
+// }
+//
+// private:
+// RefPtr<BoolPromise> BeginClose() {
+// return InvokeAsync(mIOTaskQueue, __func__,
+// []() {
+// return BoolPromise::CreateAndResolve(true, __func__);
+// })
+// ->Then(GetCurrentSerialEventTarget(), __func__,
+// [self = RefPtr<MyObject>(this)](
+// const BoolPromise::ResolveOrRejectValue&) {
+// return self->mIOTaskQueue->BeginShutdown();
+// })
+// ->Then(GetCurrentSerialEventTarget(), __func__,
+// [self = RefPtr<MyObject>(this)](
+// const ShutdownPromise::ResolveOrRejectValue&) {
+// return BoolPromise::CreateAndResolve(true, __func__);
+// });
+// }
+//
+// RefPtr<TaskQueue> mIOTaskQueue;
+// uint32_t mRegCnt = 0;
+// };
+
+template <class T>
+class Registered {
+ private:
+ RefPtr<T> 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<T> aObject) : mObject(std::move(aObject)) {
+ if (mObject) {
+ mObject->Register();
+ }
+ }
+
+ Registered<T>& operator=(decltype(nullptr)) {
+ RefPtr<T> oldObject = std::move(mObject);
+ mObject = nullptr;
+ if (oldObject) {
+ oldObject->Unregister();
+ }
+ return *this;
+ }
+
+ Registered<T>& operator=(const Registered<T>& aRhs) {
+ if (aRhs.mObject) {
+ aRhs.mObject->Register();
+ }
+ RefPtr<T> oldObject = std::move(mObject);
+ mObject = aRhs.mObject;
+ if (oldObject) {
+ oldObject->Unregister();
+ }
+ return *this;
+ }
+
+ Registered<T>& operator=(Registered<T>&& aRhs) noexcept {
+ RefPtr<T> oldObject = std::move(mObject);
+ mObject = std::move(aRhs.mObject);
+ aRhs.mObject = nullptr;
+ if (oldObject) {
+ oldObject->Unregister();
+ }
+ return *this;
+ }
+
+ const RefPtr<T>& inspect() const { return mObject; }
+
+ RefPtr<T> unwrap() {
+ RefPtr<T> 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_