APZThreadUtils.cpp (3670B)
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 #include "APZThreadUtils.h" 8 9 #include "mozilla/ClearOnShutdown.h" 10 #include "mozilla/ProfilerRunnable.h" 11 #include "mozilla/StaticMutex.h" 12 13 #include "nsISerialEventTarget.h" 14 #include "nsThreadUtils.h" 15 #include "nsXULAppAPI.h" 16 17 namespace mozilla { 18 namespace layers { 19 20 static bool sThreadAssertionsEnabled = true; 21 static StaticRefPtr<nsISerialEventTarget> sControllerThread; 22 static StaticMutex sControllerThreadMutex MOZ_UNANNOTATED; 23 24 /*static*/ 25 void APZThreadUtils::SetThreadAssertionsEnabled(bool aEnabled) { 26 StaticMutexAutoLock lock(sControllerThreadMutex); 27 sThreadAssertionsEnabled = aEnabled; 28 } 29 30 /*static*/ 31 bool APZThreadUtils::GetThreadAssertionsEnabled() { 32 StaticMutexAutoLock lock(sControllerThreadMutex); 33 return sThreadAssertionsEnabled; 34 } 35 36 /*static*/ 37 void APZThreadUtils::SetControllerThread(nsISerialEventTarget* aThread) { 38 // We must either be setting the initial controller thread, or removing it, 39 // or re-using an existing controller thread. 40 StaticMutexAutoLock lock(sControllerThreadMutex); 41 MOZ_ASSERT(!sControllerThread || !aThread || sControllerThread == aThread); 42 if (aThread != sControllerThread) { 43 // This can only happen once, on startup. 44 sControllerThread = aThread; 45 ClearOnShutdown(&sControllerThread); 46 } 47 } 48 49 /*static*/ 50 void APZThreadUtils::AssertOnControllerThread() { 51 #if DEBUG 52 if (!GetThreadAssertionsEnabled()) { 53 return; 54 } 55 StaticMutexAutoLock lock(sControllerThreadMutex); 56 MOZ_ASSERT(sControllerThread && sControllerThread->IsOnCurrentThread()); 57 #endif 58 } 59 60 /*static*/ 61 void APZThreadUtils::RunOnControllerThread( 62 RefPtr<Runnable>&& aTask, nsIEventTarget::DispatchFlags flags) { 63 RefPtr<nsISerialEventTarget> thread; 64 { 65 StaticMutexAutoLock lock(sControllerThreadMutex); 66 thread = sControllerThread; 67 } 68 RefPtr<Runnable> task = std::move(aTask); 69 70 if (!thread) { 71 // Could happen on startup or if Shutdown() got called. 72 NS_WARNING("Dropping task posted to controller thread"); 73 return; 74 } 75 76 if (thread->IsOnCurrentThread()) { 77 AUTO_PROFILE_FOLLOWING_RUNNABLE(task); 78 task->Run(); 79 } else { 80 thread->Dispatch(task.forget(), flags); 81 } 82 } 83 84 /*static*/ 85 already_AddRefed<nsISerialEventTarget> APZThreadUtils::GetControllerThread() { 86 StaticMutexAutoLock lock(sControllerThreadMutex); 87 return do_AddRef(sControllerThread); 88 } 89 90 /*static*/ 91 bool APZThreadUtils::IsControllerThread() { 92 StaticMutexAutoLock lock(sControllerThreadMutex); 93 return sControllerThread && sControllerThread->IsOnCurrentThread(); 94 } 95 96 /*static*/ 97 bool APZThreadUtils::IsControllerThreadAlive() { 98 StaticMutexAutoLock lock(sControllerThreadMutex); 99 return !!sControllerThread; 100 } 101 102 /*static*/ 103 void APZThreadUtils::DelayedDispatch(already_AddRefed<Runnable> aRunnable, 104 int aDelayMs) { 105 MOZ_ASSERT(!XRE_IsContentProcess(), 106 "ContentProcessController should only be used remotely."); 107 RefPtr<nsISerialEventTarget> thread; 108 { 109 StaticMutexAutoLock lock(sControllerThreadMutex); 110 thread = sControllerThread; 111 } 112 if (!thread) { 113 // Could happen on startup 114 NS_WARNING("Dropping task posted to controller thread"); 115 return; 116 } 117 if (aDelayMs) { 118 thread->DelayedDispatch(std::move(aRunnable), aDelayMs); 119 } else { 120 thread->Dispatch(std::move(aRunnable)); 121 } 122 } 123 124 } // namespace layers 125 } // namespace mozilla