Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef nsThreadSyncDispatch_h_
8 : #define nsThreadSyncDispatch_h_
9 :
10 : #include "mozilla/Atomics.h"
11 : #include "mozilla/DebugOnly.h"
12 :
13 : #include "nsThreadUtils.h"
14 : #include "LeakRefPtr.h"
15 :
16 0 : class nsThreadSyncDispatch : public mozilla::Runnable
17 : {
18 : public:
19 0 : nsThreadSyncDispatch(nsIThread* aOrigin, already_AddRefed<nsIRunnable>&& aTask)
20 0 : : Runnable("nsThreadSyncDispatch")
21 : , mOrigin(aOrigin)
22 0 : , mSyncTask(mozilla::Move(aTask))
23 0 : , mIsPending(true)
24 : {
25 0 : }
26 :
27 0 : bool IsPending()
28 : {
29 : // This is an atomic acquire on the origin thread.
30 0 : return mIsPending;
31 : }
32 :
33 : private:
34 0 : NS_IMETHOD Run() override
35 : {
36 0 : if (nsCOMPtr<nsIRunnable> task = mSyncTask.take()) {
37 0 : MOZ_ASSERT(!mSyncTask);
38 :
39 0 : mozilla::DebugOnly<nsresult> result = task->Run();
40 0 : MOZ_ASSERT(NS_SUCCEEDED(result),
41 : "task in sync dispatch should not fail");
42 :
43 : // We must release the task here to ensure that when the original
44 : // thread is unblocked, this task has been released.
45 0 : task = nullptr;
46 :
47 : // This is an atomic release on the target thread.
48 0 : mIsPending = false;
49 :
50 : // unblock the origin thread
51 0 : mOrigin->Dispatch(this, NS_DISPATCH_NORMAL);
52 : }
53 :
54 0 : return NS_OK;
55 : }
56 :
57 : nsCOMPtr<nsIThread> mOrigin;
58 : // The task is leaked by default when Run() is not called, because
59 : // otherwise we may release it in an incorrect thread.
60 : mozilla::LeakRefPtr<nsIRunnable> mSyncTask;
61 : mozilla::Atomic<bool, mozilla::ReleaseAcquire> mIsPending;
62 : };
63 :
64 : #endif // nsThreadSyncDispatch_h_
|