VRThread.cpp (3650B)
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 "VRThread.h" 8 #include "nsDebug.h" 9 #include "nsThreadManager.h" 10 #include "nsThread.h" 11 #include "nsThreadUtils.h" 12 13 namespace mozilla { 14 15 namespace gfx { 16 17 static const uint32_t kDefaultThreadLifeTime = 60; // in 60 seconds. 18 static const uint32_t kDelayPostTaskTime = 20000; // in 20000 ms. 19 20 VRThread::VRThread(const nsCString& aName) 21 : mThread(nullptr), mLifeTime(kDefaultThreadLifeTime), mStarted(false) { 22 mName = aName; 23 } 24 25 VRThread::~VRThread() { Shutdown(); } 26 27 void VRThread::Start() { 28 if (!mThread) { 29 nsresult rv = NS_NewNamedThread(mName, getter_AddRefs(mThread)); 30 MOZ_ASSERT(mThread); 31 32 if (NS_FAILED(rv)) { 33 MOZ_ASSERT(false, "Failed to create a vr thread."); 34 } 35 RefPtr<Runnable> runnable = 36 NewRunnableMethod<TimeStamp>("gfx::VRThread::CheckLife", this, 37 &VRThread::CheckLife, TimeStamp::Now()); 38 // Post it to the main thread for tracking the lifetime. 39 nsCOMPtr<nsIThread> mainThread; 40 rv = NS_GetMainThread(getter_AddRefs(mainThread)); 41 if (NS_FAILED(rv)) { 42 NS_WARNING("VRThread::Start() could not get Main thread"); 43 return; 44 } 45 mainThread->DelayedDispatch(runnable.forget(), kDelayPostTaskTime); 46 } 47 mStarted = true; 48 mLastActiveTime = TimeStamp::Now(); 49 } 50 51 void VRThread::Shutdown() { 52 if (mThread) { 53 if (nsThreadManager::get().IsNSThread()) { 54 mThread->Shutdown(); 55 } else { 56 NS_WARNING( 57 "VRThread::Shutdown() may only be called from an XPCOM thread"); 58 NS_DispatchToMainThread(NS_NewRunnableFunction( 59 "VRThread::Shutdown", [thread = mThread]() { thread->Shutdown(); })); 60 } 61 mThread = nullptr; 62 } 63 mStarted = false; 64 } 65 66 const nsCOMPtr<nsIThread> VRThread::GetThread() const { return mThread; } 67 68 void VRThread::PostTask(already_AddRefed<Runnable> aTask) { 69 PostDelayedTask(std::move(aTask), 0); 70 } 71 72 void VRThread::PostDelayedTask(already_AddRefed<Runnable> aTask, 73 uint32_t aTime) { 74 MOZ_ASSERT(mStarted, "Must call Start() before posting tasks."); 75 MOZ_ASSERT(mThread); 76 mLastActiveTime = TimeStamp::Now(); 77 78 if (!aTime) { 79 mThread->Dispatch(std::move(aTask), NS_DISPATCH_NORMAL); 80 } else { 81 mThread->DelayedDispatch(std::move(aTask), aTime); 82 } 83 } 84 85 void VRThread::CheckLife(TimeStamp aCheckTimestamp) { 86 // VR system is going to shutdown. 87 if (!mStarted) { 88 Shutdown(); 89 return; 90 } 91 92 const TimeDuration timeout = TimeDuration::FromSeconds(mLifeTime); 93 if ((aCheckTimestamp - mLastActiveTime) > timeout) { 94 Shutdown(); 95 } else { 96 RefPtr<Runnable> runnable = 97 NewRunnableMethod<TimeStamp>("gfx::VRThread::CheckLife", this, 98 &VRThread::CheckLife, TimeStamp::Now()); 99 // Post it to the main thread for tracking the lifetime. 100 nsCOMPtr<nsIThread> mainThread; 101 nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread)); 102 if (NS_FAILED(rv)) { 103 NS_WARNING("VRThread::CheckLife() could not get Main thread"); 104 return; 105 } 106 mainThread->DelayedDispatch(runnable.forget(), kDelayPostTaskTime); 107 } 108 } 109 110 void VRThread::SetLifeTime(uint32_t aLifeTime) { mLifeTime = aLifeTime; } 111 112 uint32_t VRThread::GetLifeTime() { return mLifeTime; } 113 114 bool VRThread::IsActive() { return !!mThread; } 115 116 } // namespace gfx 117 } // namespace mozilla