Bug 1406327 - Part 5: Checking VRListenerThread is shutdowning. draft
authorDaosheng Mu <daoshengmu@gmail.com>
Thu, 02 Nov 2017 16:01:59 +0800
changeset 694068 0b518e5e025671b4261f6ebf8e0e9c99bc455bf2
parent 694067 6cfba4678a8824d89e89f2e3e357d58633bf81ee
child 694069 6e5f6cde0573de9ef0fb6cb47286bcea97f0d1b3
push id88034
push userbmo:dmu@mozilla.com
push dateTue, 07 Nov 2017 10:40:18 +0000
bugs1406327
milestone58.0a1
Bug 1406327 - Part 5: Checking VRListenerThread is shutdowning. MozReview-Commit-ID: AJgz0NA2MOa
gfx/layers/ipc/CompositorVsyncScheduler.cpp
gfx/layers/ipc/CompositorVsyncScheduler.h
gfx/vr/VRThread.cpp
gfx/vr/VRThread.h
--- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp
+++ b/gfx/layers/ipc/CompositorVsyncScheduler.cpp
@@ -136,40 +136,31 @@ CompositorVsyncScheduler::PostCompositeT
   if (mCurrentVRListenerTask == nullptr && VRListenerThreadHolder::IsActive()) {
     const TimeDuration timeout = TimeDuration::FromSeconds(45);
     VRManager* vm = VRManager::Get();
     TimeStamp activeTime(vm->GetLastVRListenerThreadActiveTime());
 
     // Shutdown VR listener thread when no VR content in 45 sec. Shutdown threads
     // only allows to be run at the main thread.
     if (!activeTime.IsNull() && ((aCompositeTimestamp - activeTime) > timeout)) {
-      RefPtr<Runnable> runnable = NewRunnableMethod(
-        "layers::CompositorVsyncScheduler::ShutdownVRListenerThread",
-        this, &CompositorVsyncScheduler::ShutdownVRListenerThread);
-      NS_DispatchToMainThread(runnable.forget());
+      VRListenerThreadHolder::Shutdown();
     } else {
       RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
         "layers::CompositorVsyncScheduler::DispatchVREvents",
         this,
         &CompositorVsyncScheduler::DispatchVREvents,
         aCompositeTimestamp);
       mCurrentVRListenerTask = task;
       MOZ_ASSERT(VRListenerThreadHolder::Loop());
       VRListenerThreadHolder::Loop()->PostTask(Move(task.forget()));
     }
   }
 }
 
 void
-CompositorVsyncScheduler::ShutdownVRListenerThread()
-{
-  VRListenerThreadHolder::Shutdown();
-}
-
-void
 CompositorVsyncScheduler::ScheduleComposition()
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   if (!mVsyncObserver) {
     // Destroy was already called on this object.
     return;
   }
 
--- a/gfx/layers/ipc/CompositorVsyncScheduler.h
+++ b/gfx/layers/ipc/CompositorVsyncScheduler.h
@@ -78,17 +78,16 @@ private:
   virtual ~CompositorVsyncScheduler();
 
   void NotifyCompositeTaskExecuted();
   void ObserveVsync();
   void UnobserveVsync();
   void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
   void DispatchVREvents(TimeStamp aVsyncTimestamp);
   void CancelCurrentSetNeedsCompositeTask();
-  void ShutdownVRListenerThread();
 
   class Observer final : public VsyncObserver
   {
   public:
     explicit Observer(CompositorVsyncScheduler* aOwner);
     virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
     void Destroy();
   private:
--- a/gfx/vr/VRThread.cpp
+++ b/gfx/vr/VRThread.cpp
@@ -11,16 +11,18 @@
 namespace mozilla {
 
 namespace gfx {
 
 static StaticRefPtr<VRListenerThreadHolder> sVRListenerThreadHolder;
 static TimeStamp sStartTime;
 static bool sFinishedVRListenerShutDown = false;
 
+bool VRListenerThreadHolder::sShutdowning = false;
+
 VRListenerThreadHolder* GetVRListenerThreadHolder()
 {
   return sVRListenerThreadHolder;
 }
 
 base::Thread*
 VRListenerThread()
 {
@@ -91,46 +93,51 @@ VRListenerThreadHolder::CreateThread()
 void
 VRListenerThreadHolder::Start()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
   MOZ_ASSERT(!sVRListenerThreadHolder, "The VR listener thread has already been started!");
 
   sVRListenerThreadHolder = new VRListenerThreadHolder();
   sStartTime = TimeStamp::Now();
+  sShutdowning = false;
 }
 
 TimeStamp
 VRListenerThreadHolder::GetStartTime()
 {
   return sStartTime;
 }
 
-void
+/* static */ void
 VRListenerThreadHolder::Shutdown()
 {
   if (!IsActive()) {
     return;
   }
+  sShutdowning = true;
 
+  RefPtr<Runnable> runnable = NewRunnableFunction(
+    &VRListenerThreadHolder::ShutdownInternal);
+  NS_DispatchToMainThread(runnable.forget());
+}
+
+/* static */ void
+VRListenerThreadHolder::ShutdownInternal()
+{
+  MOZ_ASSERT(sShutdowning, "Only can be called by Shutdown()");
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
   MOZ_ASSERT(sVRListenerThreadHolder, "The VR listener thread has already been shut down!");
 
   sVRListenerThreadHolder = nullptr;
 
   SpinEventLoopUntil([&]() { return sFinishedVRListenerShutDown; });
 }
 
 /* static */ bool
 VRListenerThreadHolder::IsInVRListenerThread()
 {
   return VRListenerThread() &&
          VRListenerThread()->thread_id() == PlatformThread::CurrentId();
 }
 
 } // namespace gfx
-} // namespace mozilla
-
-bool
-NS_IsInVRListenerThread()
-{
-  return mozilla::gfx::VRListenerThreadHolder::IsInVRListenerThread();
-}
\ No newline at end of file
+} // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/VRThread.h
+++ b/gfx/vr/VRThread.h
@@ -22,32 +22,34 @@ public:
 
   base::Thread* GetThread() const {
     return mThread;
   }
 
   static VRListenerThreadHolder* GetSingleton();
 
   static bool IsActive() {
-    return !!GetSingleton() && !!Loop();
+    return !!GetSingleton() && !sShutdowning && !!Loop();
   }
 
   static void Start();
   static void Shutdown();
   static MessageLoop* Loop();
   static bool IsInVRListenerThread();
   static TimeStamp GetStartTime();
 
 private:
   ~VRListenerThreadHolder();
 
   static base::Thread* CreateThread();
   static void DestroyThread(base::Thread* aThread);
+  static void ShutdownInternal();
 
   base::Thread* const mThread;
+  static bool sShutdowning;
 };
 
 base::Thread* VRListenerThread();
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // GFX_VR_THREAD_H
\ No newline at end of file