From 0cdb8edc9530037d50f13172d6a91ecb23e78c0a Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Tue, 22 Dec 2015 15:26:26 +0000 Subject: [PATCH] Ensure Update/Render thread does not go to sleep too early Change-Id: I05e1a69a2e2538b1fd308c500b5ac2c0f8e849e2 --- .../combined-update-render-controller.cpp | 42 +++++++++++++++++----- .../combined-update-render-controller.h | 10 ++++-- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/adaptors/base/combined-update-render/combined-update-render-controller.cpp b/adaptors/base/combined-update-render/combined-update-render-controller.cpp index 5159426..bb3edfe 100644 --- a/adaptors/base/combined-update-render/combined-update-render-controller.cpp +++ b/adaptors/base/combined-update-render/combined-update-render-controller.cpp @@ -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 diff --git a/adaptors/base/combined-update-render/combined-update-render-controller.h b/adaptors/base/combined-update-render/combined-update-render-controller.h index 6c87bba..9179c6b 100644 --- a/adaptors/base/combined-update-render/combined-update-render-controller.h +++ b/adaptors/base/combined-update-render/combined-update-render-controller.h @@ -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). -- 2.7.4