xpcom/threads/SyncRunnable.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:e95f81ae20a2
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/. */
5
6 #ifndef mozilla_SyncRunnable_h
7 #define mozilla_SyncRunnable_h
8
9 #include "nsThreadUtils.h"
10 #include "mozilla/Monitor.h"
11
12 namespace mozilla {
13
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 { }
38
39 void DispatchToThread(nsIEventTarget* thread,
40 bool forceDispatch = false)
41 {
42 nsresult rv;
43 bool on;
44
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 }
53
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 }
62
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 }
70
71 protected:
72 NS_IMETHODIMP Run()
73 {
74 mRunnable->Run();
75
76 mozilla::MonitorAutoLock lock(mMonitor);
77 MOZ_ASSERT(!mDone);
78
79 mDone = true;
80 mMonitor.Notify();
81
82 return NS_OK;
83 }
84
85 private:
86 nsCOMPtr<nsIRunnable> mRunnable;
87 mozilla::Monitor mMonitor;
88 bool mDone;
89 };
90
91 } // namespace mozilla
92
93 #endif // mozilla_SyncRunnable_h

mercurial