[vlmc-devel] ClipWorkflow: Rework the state locking model
Hugo Beauzée-Luyssen
git at videolan.org
Sun Jan 26 22:08:42 CET 2014
vlmc | branch: master | Hugo Beauzée-Luyssen <hugo at beauzee.fr> | Sat Jan 25 17:35:03 2014 +0200| [c5e0682bf95805d7c5bd1cb794d06a68dfe60a6a] | committer: Hugo Beauzée-Luyssen
ClipWorkflow: Rework the state locking model
> http://git.videolan.org/gitweb.cgi/vlmc.git/?a=commit;h=c5e0682bf95805d7c5bd1cb794d06a68dfe60a6a
---
src/Workflow/ClipWorkflow.cpp | 45 +++++++++++++++---------------------
src/Workflow/ClipWorkflow.h | 18 +++++----------
src/Workflow/TrackWorkflow.cpp | 50 +++++++++++-----------------------------
3 files changed, 39 insertions(+), 74 deletions(-)
diff --git a/src/Workflow/ClipWorkflow.cpp b/src/Workflow/ClipWorkflow.cpp
index 3fc5ee6..80020c4 100644
--- a/src/Workflow/ClipWorkflow.cpp
+++ b/src/Workflow/ClipWorkflow.cpp
@@ -58,7 +58,8 @@ ClipWorkflow::~ClipWorkflow()
void
ClipWorkflow::initialize()
{
- setState( ClipWorkflow::Initializing );
+ QWriteLocker lock( m_stateLock );
+ m_state = ClipWorkflow::Initializing;
m_vlcMedia = new LibVLCpp::Media( m_clipHelper->clip()->getMedia()->mrl() );
initializeVlcOutput();
@@ -112,7 +113,7 @@ ClipWorkflow::getState() const
void
ClipWorkflow::clipEndReached()
{
- setState( EndReached );
+ m_state = EndReached;
}
void
@@ -164,19 +165,6 @@ ClipWorkflow::setTime( qint64 time )
}
}
-void
-ClipWorkflow::setState( State state )
-{
- QWriteLocker lock( m_stateLock );
- m_state = state;
-}
-
-QReadWriteLock*
-ClipWorkflow::getStateLock()
-{
- return m_stateLock;
-}
-
bool
ClipWorkflow::waitForCompleteInit()
{
@@ -211,8 +199,10 @@ ClipWorkflow::postGetOutput()
if ( m_state == ClipWorkflow::Paused )
{
m_state = ClipWorkflow::UnpauseRequired;
-// This will act like an "unpause";
+ //This will act like an "unpause";
m_mediaPlayer->pause();
+ // Since we use DirectConnection for mediaPlayerUnpaused(), the media player should be
+ // "Rendering" at this point.
}
}
}
@@ -224,8 +214,11 @@ ClipWorkflow::commonUnlock()
//no one is available : we would spawn a new buffer, thus modifying the number of available buffers
if ( getNbComputedBuffers() >= getMaxComputedBuffers() )
{
- setState( ClipWorkflow::PauseRequired );
+ QWriteLocker lock( m_stateLock );
+ m_state = ClipWorkflow::PauseRequired;
m_mediaPlayer->pause();
+ // Since we use DirectConnection for mediaPlayerPaused(), the media player should be
+ // "Paused" at this point.
}
}
@@ -247,14 +240,14 @@ ClipWorkflow::computePtsDiff( qint64 pts )
void
ClipWorkflow::mediaPlayerPaused()
{
- setState( ClipWorkflow::Paused );
+ m_state = ClipWorkflow::Paused;
m_beginPausePts = mdate();
}
void
ClipWorkflow::mediaPlayerUnpaused()
{
- setState( ClipWorkflow::Rendering );
+ m_state = ClipWorkflow::Rendering;
m_pauseDuration = mdate() - m_beginPausePts;
}
@@ -276,13 +269,13 @@ void
ClipWorkflow::mute()
{
stop();
- setState( Muted );
+ m_state = Muted;
}
void
ClipWorkflow::unmute()
{
- setState( Stopped );
+ m_state = Stopped;
}
void
@@ -306,17 +299,17 @@ void
ClipWorkflow::errorEncountered()
{
stopRenderer();
- setState( Error );
+ m_state = Error;
emit error();
}
bool
ClipWorkflow::shouldRender() const
{
- QReadLocker lock( m_stateLock );
- return ( m_state != ClipWorkflow::Error &&
- m_state != ClipWorkflow::Stopped &&
- m_state != ClipWorkflow::Stopping );
+ ClipWorkflow::State state = getState();
+ return ( state != ClipWorkflow::Error &&
+ state != ClipWorkflow::Stopped &&
+ state != ClipWorkflow::Stopping );
}
void
diff --git a/src/Workflow/ClipWorkflow.h b/src/Workflow/ClipWorkflow.h
index 4f86922..7fa1afc 100644
--- a/src/Workflow/ClipWorkflow.h
+++ b/src/Workflow/ClipWorkflow.h
@@ -74,7 +74,7 @@ class ClipWorkflow : public EffectUser
/// \brief Used when end is reached, IE no more frame has to be rendered, but the trackworkflow
/// may eventually ask for some.
EndReached, //4
- // Here starts internal states :
+ // Here start internal states :
/// \brief This state will be used when an unpause
/// has been required
UnpauseRequired, //5
@@ -135,9 +135,6 @@ class ClipWorkflow : public EffectUser
/**
* Returns the current workflow state.
- * Be carrefull, as this function is NOT thread safe, and return the
- * state without locking the state.
- * It's your job to do it, by calling the getStateLock() method.
*/
State getState() const;
@@ -175,13 +172,6 @@ class ClipWorkflow : public EffectUser
*/
void queryStateChange( State newState );
- /**
- * This returns the QReadWriteLock that protects the ClipWorkflow's state.
- * It should be use to lock the value when checking states from outside this
- * class.
- */
- QReadWriteLock* getStateLock();
-
bool waitForCompleteInit();
virtual void* getLockCallback() const = 0;
@@ -218,7 +208,6 @@ class ClipWorkflow : public EffectUser
virtual Type effectType() const;
private:
- void setState( State state );
void adjustBegin();
protected:
@@ -244,6 +233,11 @@ class ClipWorkflow : public EffectUser
virtual void releasePrealocated() = 0;
private:
+ /**
+ * @brief m_initWaitCond Used to synchronize initialization.
+ *
+ * The associated lock is m_stateLock
+ */
QWaitCondition *m_initWaitCond;
/**
* \brief Used by the trackworkflow to query a clipworkflow resync.
diff --git a/src/Workflow/TrackWorkflow.cpp b/src/Workflow/TrackWorkflow.cpp
index 88d84d5..61712ed 100644
--- a/src/Workflow/TrackWorkflow.cpp
+++ b/src/Workflow/TrackWorkflow.cpp
@@ -176,21 +176,18 @@ TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
ClipWorkflow::GetMode mode = ( paused == false || renderOneFrame == true ?
ClipWorkflow::Pop : ClipWorkflow::Get );
- cw->getStateLock()->lockForRead();
- if ( cw->getState() == ClipWorkflow::Rendering ||
- cw->getState() == ClipWorkflow::Paused ||
- cw->getState() == ClipWorkflow::PauseRequired ||
- cw->getState() == ClipWorkflow::UnpauseRequired )
+ ClipWorkflow::State state = cw->getState();
+ if ( state == ClipWorkflow::Rendering ||
+ state == ClipWorkflow::Paused ||
+ state == ClipWorkflow::PauseRequired ||
+ state == ClipWorkflow::UnpauseRequired )
{
- cw->getStateLock()->unlock();
-
if ( cw->isResyncRequired() == true || needRepositioning == true )
adjustClipTime( currentFrame, start, cw );
return cw->getOutput( mode, currentFrame - start );
}
- else if ( cw->getState() == ClipWorkflow::Stopped )
+ else if ( state == ClipWorkflow::Stopped )
{
- cw->getStateLock()->unlock();
cw->initialize();
//If the init failed, don't even try to call getOutput.
if ( cw->waitForCompleteInit() == false )
@@ -203,17 +200,15 @@ TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
}
return cw->getOutput( mode, currentFrame - start );
}
- else if ( cw->getState() == ClipWorkflow::EndReached ||
- cw->getState() == ClipWorkflow::Muted ||
- cw->getState() == ClipWorkflow::Error )
+ else if ( state == ClipWorkflow::EndReached ||
+ state == ClipWorkflow::Muted ||
+ state == ClipWorkflow::Error )
{
- cw->getStateLock()->unlock();
//The stopClipWorkflow() method will take care of that.
}
else
{
- qCritical() << "Unexpected state:" << cw->getState();
- cw->getStateLock()->unlock();
+ qCritical() << "Unexpected state:" << state;
}
return NULL;
}
@@ -221,31 +216,18 @@ TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
void
TrackWorkflow::preloadClip( ClipWorkflow* cw )
{
- cw->getStateLock()->lockForRead();
-
if ( cw->getState() == ClipWorkflow::Stopped )
- {
- cw->getStateLock()->unlock();
cw->initialize();
- return ;
- }
- cw->getStateLock()->unlock();
}
void
TrackWorkflow::stopClipWorkflow( ClipWorkflow* cw )
{
// qDebug() << "Stopping clip workflow";
- cw->getStateLock()->lockForRead();
-
if ( cw->getState() == ClipWorkflow::Stopped ||
cw->getState() == ClipWorkflow::Muted ||
cw->getState() == ClipWorkflow::Error )
- {
- cw->getStateLock()->unlock();
return ;
- }
- cw->getStateLock()->unlock();
cw->stop();
}
@@ -259,7 +241,6 @@ TrackWorkflow::hasNoMoreFrameToRender( qint64 currentFrame ) const
ClipWorkflow* cw = it.value();
//Check if the Clip is in error state. If so, don't bother checking anything else.
{
- QReadLocker lock( cw->getStateLock() );
if ( cw->getState() == ClipWorkflow::Error )
return true;
}
@@ -632,16 +613,13 @@ TrackWorkflow::stopFrameComputing()
{
ClipWorkflow* cw = it.value();
- cw->getStateLock()->lockForRead();
-
- if ( cw->getState() == ClipWorkflow::Stopped ||
- cw->getState() == ClipWorkflow::Muted ||
- cw->getState() == ClipWorkflow::Error )
+ ClipWorkflow::State state = cw->getState();
+ if ( state == ClipWorkflow::Stopped ||
+ state == ClipWorkflow::Muted ||
+ state == ClipWorkflow::Error )
{
- cw->getStateLock()->unlock();
return ;
}
- cw->getStateLock()->unlock();
cw->stopRenderer();
++it;
}
More information about the Vlmc-devel
mailing list