Permalink
Browse files

[dvdplayer] rewrite syncronization message to be more efficient

This new sync message will now wakeup directly on object release
to check situation. It should reduce any scheduling delay that
previous implementation had.
  • Loading branch information...
elupus committed Jun 14, 2012
1 parent 095624e commit 9303d3c092dd0e0ad9c4522605a8fd38e0dfa6e9
Showing with 80 additions and 18 deletions.
  1. +65 −14 xbmc/cores/dvdplayer/DVDMessage.cpp
  2. +7 −4 xbmc/cores/dvdplayer/DVDMessage.h
  3. +8 −0 xbmc/utils/MathUtils.h
@@ -24,35 +24,86 @@
#include "DVDDemuxers/DVDDemuxUtils.h"
#include "DVDStreamInfo.h"
#include "utils/TimeUtils.h"
+#include "utils/log.h"
+#include "threads/CriticalSection.h"
+#include "threads/Condition.h"
+#include "threads/SystemClock.h"
+#include "utils/MathUtils.h"
+class CDVDMsgGeneralSynchronizePriv
+{
+public:
+ CDVDMsgGeneralSynchronizePriv(DWORD timeout, DWORD sources)

This comment has been minimized.

Show comment Hide comment
@elupus

elupus Jun 18, 2012

Owner
@elupus

elupus via email Jun 18, 2012

Owner
+ : timeout(timeout)
+ , sources(sources ? sources : SYNCSOURCE_ALL)
+ , reached(0)
+ {}
+ unsigned int sources;
+ unsigned int reached;
+ CCriticalSection section;
+ XbmcThreads::ConditionVariable condition;
+ XbmcThreads::EndTime timeout;
+};
/**
* CDVDMsgGeneralSynchronize --- GENERAL_SYNCRONIZR
*/
CDVDMsgGeneralSynchronize::CDVDMsgGeneralSynchronize(DWORD timeout, DWORD sources) : CDVDMsg(GENERAL_SYNCHRONIZE)
+ , m_p(new CDVDMsgGeneralSynchronizePriv(timeout, sources))
{
- if( sources )
- m_sources = sources;
- else
- m_sources = SYNCSOURCE_ALL;
+}
- m_objects = 0;
- m_timeout = timeout;
+CDVDMsgGeneralSynchronize::~CDVDMsgGeneralSynchronize()
+{
+ delete m_p;
}
-void CDVDMsgGeneralSynchronize::Wait(volatile bool *abort, DWORD source)
+bool CDVDMsgGeneralSynchronize::Wait(unsigned long milliseconds, DWORD source)
{
+ if(source == 0)
+ source = SYNCSOURCE_OWNER;
+
/* if we are not requested to wait on this object just return, reference count will be decremented */
- if (source && !(m_sources & source)) return;
+ if (!(m_p->sources & source))
+ return true;
+
+ CSingleLock lock(m_p->section);
- AtomicIncrement(&m_objects);
+ XbmcThreads::EndTime timeout(milliseconds);
- XbmcThreads::EndTime timeout(m_timeout);
+ m_p->reached |= source & m_p->sources;
- if (abort)
- while( m_objects < GetNrOfReferences() && !timeout.IsTimePast() && !(*abort)) Sleep(1);
- else
- while( m_objects < GetNrOfReferences() && !timeout.IsTimePast() ) Sleep(1);
+ while( (long)MathUtils::bitcount(m_p->reached) < GetNrOfReferences() )
+ {
+ milliseconds = std::min(m_p->timeout.MillisLeft(), timeout.MillisLeft());
+ if(m_p->condition.wait(lock, milliseconds))
+ continue;
+ if(m_p->timeout.IsTimePast())
+ return true; /* global timeout, we are done */
+ if(timeout.IsTimePast())
+ return false; /* request timeout, should be retried */
+ }
+ return true;
+}
+
+void CDVDMsgGeneralSynchronize::Wait(volatile bool *abort, DWORD source)
+{
+ while(!Wait(100, source))
+ {
+ if(abort && *abort)
+ return;
+ }
+}
+
+long CDVDMsgGeneralSynchronize::Release()
+{
+ CSingleLock lock(m_p->section);
+ long count = --m_refs;
+ m_p->condition.notifyAll();
+ lock.Leave();
+ if (count == 0)
+ delete this;
+ return count;
}
/**
@@ -147,20 +147,23 @@ class CDVDMsgGeneralResync : public CDVDMsg
#define SYNCSOURCE_AUDIO 0x00000001
#define SYNCSOURCE_VIDEO 0x00000002
#define SYNCSOURCE_SUB 0x00000004
-#define SYNCSOURCE_ALL (SYNCSOURCE_AUDIO | SYNCSOURCE_VIDEO | SYNCSOURCE_SUB)
+#define SYNCSOURCE_OWNER 0x80000000 /* only allowed for the constructor of the object */
+#define SYNCSOURCE_ALL (SYNCSOURCE_AUDIO | SYNCSOURCE_VIDEO | SYNCSOURCE_SUB | SYNCSOURCE_OWNER)
+class CDVDMsgGeneralSynchronizePriv;
class CDVDMsgGeneralSynchronize : public CDVDMsg
{
public:
CDVDMsgGeneralSynchronize(DWORD timeout, DWORD sources);
+ ~CDVDMsgGeneralSynchronize();
+ virtual long Release();
// waits until all threads waiting, released the object
// if abort is set somehow
+ bool Wait(unsigned long ms , DWORD source);
void Wait(volatile bool *abort, DWORD source);
private:
- DWORD m_sources;
- long m_objects;
- unsigned int m_timeout;
+ class CDVDMsgGeneralSynchronizePriv* m_p;
};
template <typename T>
View
@@ -208,6 +208,14 @@ namespace MathUtils
return (a < 0) ? -a : a;
}
+ inline unsigned bitcount(unsigned v)
+ {
+ unsigned c = 0;
+ for (c = 0; v; c++)
+ v &= v - 1; // clear the least significant bit set
+ return c;
+ }
+
inline void hack()
{
// stupid hack to keep compiler from dropping these

0 comments on commit 9303d3c

Please sign in to comment.