tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AsyncBlockers.h (2864B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set sw=2 ts=8 et ft=cpp : */
      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 #ifndef mozilla_ipc_AsyncBlockers_h
      8 #define mozilla_ipc_AsyncBlockers_h
      9 
     10 #include "mozilla/MozPromise.h"
     11 #include "mozilla/ThreadSafety.h"
     12 #include "nsTArray.h"
     13 
     14 // FIXME: when bug 1760855 is fixed, it should not be required anymore
     15 
     16 namespace mozilla::ipc {
     17 
     18 /**
     19 * AsyncBlockers provide a simple registration service that allows to suspend
     20 * completion of a particular task until all registered entries have been
     21 * cleared. This can be used to implement a similar service to
     22 * nsAsyncShutdownService in processes where it wouldn't normally be available.
     23 * This class is thread-safe.
     24 */
     25 class AsyncBlockers {
     26 public:
     27  AsyncBlockers()
     28      : mLock("AsyncRegistrar"),
     29        mPromise(new GenericPromise::Private(__func__)) {}
     30  void Register(void* aBlocker) {
     31    MutexAutoLock lock(mLock);
     32    mBlockers.InsertElementSorted(aBlocker);
     33  }
     34  void Deregister(void* aBlocker) {
     35    MutexAutoLock lock(mLock);
     36    MOZ_ASSERT(mBlockers.ContainsSorted(aBlocker));
     37    MOZ_ALWAYS_TRUE(mBlockers.RemoveElementSorted(aBlocker));
     38    MaybeResolve();
     39  }
     40  RefPtr<GenericPromise> WaitUntilClear(uint32_t aTimeOutInMs = 0) {
     41    {
     42      MutexAutoLock lock(mLock);
     43      MaybeResolve();
     44    }
     45 
     46    if (aTimeOutInMs > 0) {
     47      GetCurrentSerialEventTarget()->DelayedDispatch(
     48          NS_NewRunnableFunction("AsyncBlockers::WaitUntilClear",
     49                                 [promise = mPromise]() {
     50                                   // The AsyncBlockers object may have been
     51                                   // deleted by now and the object isn't
     52                                   // refcounted (nor do we want it to be). We
     53                                   // can unconditionally resolve the promise
     54                                   // even it has already been resolved as
     55                                   // MozPromise are thread-safe and will just
     56                                   // ignore the action if already resolved.
     57                                   promise->Resolve(true, __func__);
     58                                 }),
     59          aTimeOutInMs);
     60    }
     61 
     62    return mPromise;
     63  }
     64 
     65  virtual ~AsyncBlockers() { mPromise->Resolve(true, __func__); }
     66 
     67 private:
     68  void MaybeResolve() MOZ_REQUIRES(mLock) {
     69    mLock.AssertCurrentThreadOwns();
     70    if (!mBlockers.IsEmpty()) {
     71      return;
     72    }
     73    mPromise->Resolve(true, __func__);
     74  }
     75  Mutex mLock;
     76  nsTArray<void*> mBlockers MOZ_GUARDED_BY(mLock);
     77  const RefPtr<GenericPromise::Private> mPromise;
     78 };
     79 
     80 }  // namespace mozilla::ipc
     81 
     82 #endif  // mozilla_ipc_AsyncBlockers_h