xpcom/threads/SyncRunnable.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 12; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_SyncRunnable_h
     7 #define mozilla_SyncRunnable_h
     9 #include "nsThreadUtils.h"
    10 #include "mozilla/Monitor.h"
    12 namespace mozilla {
    14 /**
    15  * This class will wrap a nsIRunnable and dispatch it to the main thread
    16  * synchronously. This is different from nsIEventTarget.DISPATCH_SYNC:
    17  * this class does not spin the event loop waiting for the event to be
    18  * dispatched. This means that you don't risk reentrance from pending
    19  * messages, but you must be sure that the target thread does not ever block
    20  * on this thread, or else you will deadlock.
    21  *
    22  * Typical usage:
    23  * nsRefPtr<SyncRunnable> sr = new SyncRunnable(new myrunnable...());
    24  * sr->DispatchToThread(t);
    25  *
    26  * We also provide a convenience wrapper:
    27  * SyncRunnable::DispatchToThread(new myrunnable...());
    28  *
    29  */
    30 class SyncRunnable : public nsRunnable
    31 {
    32 public:
    33   SyncRunnable(nsIRunnable* r)
    34     : mRunnable(r)
    35     , mMonitor("SyncRunnable")
    36     , mDone(false)
    37   { }
    39   void DispatchToThread(nsIEventTarget* thread,
    40                         bool forceDispatch = false)
    41   {
    42     nsresult rv;
    43     bool on;
    45     if (!forceDispatch) {
    46       rv = thread->IsOnCurrentThread(&on);
    47       MOZ_ASSERT(NS_SUCCEEDED(rv));
    48       if (NS_SUCCEEDED(rv) && on) {
    49         mRunnable->Run();
    50         return;
    51       }
    52     }
    54     rv = thread->Dispatch(this, NS_DISPATCH_NORMAL);
    55     if (NS_SUCCEEDED(rv)) {
    56       mozilla::MonitorAutoLock lock(mMonitor);
    57       while (!mDone) {
    58         lock.Wait();
    59       }
    60     }
    61   }
    63   static void DispatchToThread(nsIEventTarget* thread,
    64                                nsIRunnable* r,
    65                                bool forceDispatch = false)
    66   {
    67     nsRefPtr<SyncRunnable> s(new SyncRunnable(r));
    68     s->DispatchToThread(thread, forceDispatch);
    69   }
    71 protected:
    72   NS_IMETHODIMP Run()
    73   {
    74     mRunnable->Run();
    76     mozilla::MonitorAutoLock lock(mMonitor);
    77     MOZ_ASSERT(!mDone);
    79     mDone = true;
    80     mMonitor.Notify();
    82     return NS_OK;
    83   }
    85 private:
    86   nsCOMPtr<nsIRunnable> mRunnable;
    87   mozilla::Monitor mMonitor;
    88   bool mDone;
    89 };
    91 } // namespace mozilla
    93 #endif // mozilla_SyncRunnable_h

mercurial