Ensure Update/Render thread does not go to sleep too early 72/55272/2
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 22 Dec 2015 15:26:26 +0000 (15:26 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 22 Dec 2015 18:09:43 +0000 (18:09 +0000)
Change-Id: I05e1a69a2e2538b1fd308c500b5ac2c0f8e849e2

adaptors/base/combined-update-render/combined-update-render-controller.cpp
adaptors/base/combined-update-render/combined-update-render-controller.h

index 5159426..bb3edfe 100644 (file)
@@ -103,6 +103,8 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS
   mRunning( FALSE ),
   mUpdateRenderRunCount( 0 ),
   mDestroyUpdateRenderThread( FALSE ),
+  mUpdateRenderThreadCanSleep( FALSE ),
+  mPendingRequestUpdate( FALSE ),
   mNewSurface( NULL ),
   mPostRendering( FALSE )
 {
@@ -236,6 +238,9 @@ void CombinedUpdateRenderController::RequestUpdate()
 
     RunUpdateRenderThread( CONTINUOUS, false /* No animation progression */ );
   }
+
+  ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition );
+  mPendingRequestUpdate = TRUE;
 }
 
 void CombinedUpdateRenderController::RequestUpdateOnce()
@@ -291,6 +296,7 @@ void CombinedUpdateRenderController::RunUpdateRenderThread( int numberOfCycles,
 {
   ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
   mUpdateRenderRunCount = numberOfCycles;
+  mUpdateRenderThreadCanSleep = FALSE;
   mUseElapsedTimeAfterWait = useElapsedTime;
   LOG_COUNTER_EVENT( "mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait );
   mUpdateRenderThreadWaitCondition.Notify( lock );
@@ -312,7 +318,8 @@ void CombinedUpdateRenderController::StopUpdateRenderThread()
 bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused()
 {
   ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
-  return mUpdateRenderRunCount != CONTINUOUS; // Report paused if NOT continuously running
+  return ( mUpdateRenderRunCount != CONTINUOUS ) || // Report paused if NOT continuously running
+         mUpdateRenderThreadCanSleep;               // Report paused if sleeping
 }
 
 void CombinedUpdateRenderController::ProcessSleepRequest()
@@ -325,12 +332,14 @@ void CombinedUpdateRenderController::ProcessSleepRequest()
     --mUpdateRequestCount;
   }
 
-  // Only sleep if our update-request count is 0
+  // Can sleep if our update-request count is 0
+  // Update/Render thread can choose to carry on updating if it determines more update/renders are required
   if( mUpdateRequestCount == 0 )
   {
     LOG_EVENT( "Going to sleep" );
 
-    PauseUpdateRenderThread();
+    ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
+    mUpdateRenderThreadCanSleep = TRUE;
   }
 }
 
@@ -359,8 +368,9 @@ void CombinedUpdateRenderController::UpdateRenderThread()
   LOG_UPDATE_RENDER( "THREAD INITIALISED" );
 
   bool useElapsedTime = true;
+  bool updateRequired = true;
 
-  while( UpdateRenderReady( useElapsedTime ) )
+  while( UpdateRenderReady( useElapsedTime, updateRequired ) )
   {
     LOG_UPDATE_RENDER_TRACE;
 
@@ -449,8 +459,13 @@ void CombinedUpdateRenderController::UpdateRenderThread()
         ! renderStatus.NeedsUpdate() )
     {
       mSleepTrigger->Trigger();
+      updateRequired = false;
       LOG_UPDATE_RENDER( "Sleep Triggered" );
     }
+    else
+    {
+      updateRequired = true;
+    }
 
     //////////////////////////////
     // FRAME TIME
@@ -470,15 +485,21 @@ void CombinedUpdateRenderController::UpdateRenderThread()
   mEnvironmentOptions.UnInstallLogFunction();
 }
 
-bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime )
+bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired )
 {
   useElapsedTime = true;
 
   ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition );
-  while( ! mUpdateRenderRunCount && // Should try to wait if event-thread has paused the Update/Render thread
+  while( ( ! mUpdateRenderRunCount || // Should try to wait if event-thread has paused the Update/Render thread
+           ( mUpdateRenderThreadCanSleep && ! updateRequired && ! mPendingRequestUpdate ) ) && // Ensure we wait if we're supposed to be sleeping AND do not require another update
          ! mDestroyUpdateRenderThread && // Ensure we don't wait if the update-render-thread is supposed to be destroyed
          ! mNewSurface ) // Ensure we don't wait if we need to replace the surface
   {
+    LOG_UPDATE_RENDER( "WAIT: mUpdateRenderRunCount:       %d", mUpdateRenderRunCount );
+    LOG_UPDATE_RENDER( "      mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
+    LOG_UPDATE_RENDER( "      mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
+    LOG_UPDATE_RENDER( "      mNewSurface:                 %d", mNewSurface );
+
     mUpdateRenderThreadWaitCondition.Wait( updateLock );
 
     if( ! mUseElapsedTimeAfterWait )
@@ -487,9 +508,14 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime )
     }
   }
 
-  mUseElapsedTimeAfterWait = FALSE;
+  LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderRunCount:       %d", mUpdateRenderRunCount );
+  LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
+  LOG_COUNTER_UPDATE_RENDER( "mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
+  LOG_COUNTER_UPDATE_RENDER( "mNewSurface:                 %d", mNewSurface );
 
-  LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderRunCount: %d", mUpdateRenderRunCount );
+  mUseElapsedTimeAfterWait = FALSE;
+  mUpdateRenderThreadCanSleep = FALSE;
+  mPendingRequestUpdate = FALSE;
 
   // If we've been asked to run Update/Render cycles a finite number of times then decrement so we wait after the
   // requested number of cycles
index 6c87bba..9179c6b 100644 (file)
@@ -192,11 +192,12 @@ private:
   /**
    * Called by the Update/Render Thread which ensures a wait if required.
    *
-   * @param[out] useElapsedTime If true when returned, then the actual elapsed time will be used for animation.
-   *                            If false when returned, then there should NOT be any animation progression in the next Update.
+   * @param[out] useElapsedTime  If true when returned, then the actual elapsed time will be used for animation.
+   *                             If false when returned, then there should NOT be any animation progression in the next Update.
+   * @param[in]  updateRequired  Whether another update is required.
    * @return false, if the thread should stop.
    */
-  bool UpdateRenderReady( bool& useElapsedTime );
+  bool UpdateRenderReady( bool& useElapsedTime, bool updateRequired );
 
   /**
    * Checks to see if the surface needs to be replaced.
@@ -301,6 +302,9 @@ private:
 
   volatile int                      mUpdateRenderRunCount;             ///< The number of times Update/Render cycle should run. If -1, then will run continuously (set by the event-thread, read by v-sync-thread).
   volatile unsigned int             mDestroyUpdateRenderThread;        ///< Whether the Update/Render thread be destroyed (set by the event-thread, read by the update-render-thread).
+  volatile unsigned int             mUpdateRenderThreadCanSleep;       ///< Whether the Update/Render thread can sleep (set by the event-thread, read by the update-render-thread).
+  volatile unsigned int             mPendingRequestUpdate;             ///< Is set as soon as an RequestUpdate is made and unset when the next update happens (set by the event-thread and update-render thread, read by the update-render-thread).
+                                                                       ///< Ensures we do not go to sleep if we have not processed the most recent update-request.
 
   volatile unsigned int             mUseElapsedTimeAfterWait;          ///< Whether we should use the elapsed time after waiting (set by the event-thread, read by the update-render-thread).