Skip to content

Commit

Permalink
Rework the SignalMonitor thread start/stop, add thread registration a…
Browse files Browse the repository at this point in the history
…nd remove some unused methods.

Conflicts:

	mythtv/libs/libmythtv/signalmonitor.cpp
  • Loading branch information
daniel-kristjansson committed Jun 17, 2011
1 parent 5c981e5 commit 6285825
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 140 deletions.
36 changes: 2 additions & 34 deletions mythtv/libs/libmythtv/dtvsignalmonitor.cpp
Expand Up @@ -59,9 +59,9 @@ DTVChannel *DTVSignalMonitor::GetDTVChannel(void)
return dynamic_cast<DTVChannel*>(channel);
}

QStringList DTVSignalMonitor::GetStatusList(bool kick)
QStringList DTVSignalMonitor::GetStatusList(void) const
{
QStringList list = SignalMonitor::GetStatusList(kick);
QStringList list = SignalMonitor::GetStatusList();
QMutexLocker locker(&statusLock);

// mpeg tables
Expand Down Expand Up @@ -526,35 +526,3 @@ bool DTVSignalMonitor::IsAllGood(void) const

return true;
}

/** \fn SignalMonitor::WaitForLock(int)
* \brief Wait for a StatusSignaLock(int) of true.
*
* This can be called only after the signal
* monitoring thread has been started.
*
* \param timeout maximum time to wait in milliseconds.
* \return true if signal was acquired.
*/
bool DTVSignalMonitor::WaitForLock(int timeout)
{
statusLock.lock();
if (-1 == timeout)
timeout = signalLock.GetTimeout();
statusLock.unlock();
if (timeout < 0)
return false;

MythTimer t;
t.start();
while (t.elapsed()<timeout && running)
{
SignalMonitorList slist =
SignalMonitorValue::Parse(GetStatusList());
if (SignalMonitorValue::AllGood(slist))
return true;
usleep(250);
}

return false;
}
4 changes: 1 addition & 3 deletions mythtv/libs/libmythtv/dtvsignalmonitor.h
Expand Up @@ -25,7 +25,7 @@ class DTVSignalMonitor : public SignalMonitor,
virtual ~DTVSignalMonitor();

public:
virtual QStringList GetStatusList(bool kick = true);
virtual QStringList GetStatusList(void) const;

void SetChannel(int major, int minor);
int GetMajorChannel() const { return majorChannel; }
Expand Down Expand Up @@ -75,8 +75,6 @@ class DTVSignalMonitor : public SignalMonitor,

bool IsAllGood(void) const;

bool WaitForLock(int timeout=-1);

// MPEG
void HandlePAT(const ProgramAssociationTable*);
void HandleCAT(const ConditionalAccessTable*) {}
Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmythtv/dvbsignalmonitor.cpp
Expand Up @@ -153,9 +153,9 @@ void DVBSignalMonitor::Stop(void)
VERBOSE(VB_CHANNEL, LOC + "Stop() -- end");
}

QStringList DVBSignalMonitor::GetStatusList(bool kick)
QStringList DVBSignalMonitor::GetStatusList(void) const
{
QStringList list = DTVSignalMonitor::GetStatusList(kick);
QStringList list = DTVSignalMonitor::GetStatusList();
statusLock.lock();
if (HasFlags(kDVBSigMon_WaitForSNR))
list<<signalToNoise.GetName()<<signalToNoise.GetStatus();
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/dvbsignalmonitor.h
Expand Up @@ -20,7 +20,7 @@ class DVBSignalMonitor: public DTVSignalMonitor
kDVBSigMon_WaitForBER | kDVBSigMon_WaitForUB);
virtual ~DVBSignalMonitor();

virtual QStringList GetStatusList(bool kick);
virtual QStringList GetStatusList(void) const;
void Stop(void);

virtual void SetRotorTarget(float target);
Expand Down
124 changes: 29 additions & 95 deletions mythtv/libs/libmythtv/signalmonitor.cpp
Expand Up @@ -178,7 +178,6 @@ SignalMonitor::SignalMonitor(int _capturecardnum, ChannelBase *_channel,
: channel(_channel),
capturecardnum(_capturecardnum), flags(wait_for_mask),
update_rate(25), minimum_update_rate(5),
running(false), exit(false),
update_done(false), notify_frontend(true),
eit_scan(false),
signalLock (QObject::tr("Signal Lock"), "slock",
Expand All @@ -187,6 +186,7 @@ SignalMonitor::SignalMonitor(int _capturecardnum, ChannelBase *_channel,
0, true, 0, 100, 0),
scriptStatus (QObject::tr("Script Status"), "script",
3, true, 0, 3, 0),
running(false), exit(false),
statusLock(QMutex::Recursive)
{
if (!channel->IsExternalChannelChangeSupported())
Expand Down Expand Up @@ -233,11 +233,10 @@ void SignalMonitor::Start()
DBG_SM("Start", "begin");
{
QMutexLocker locker(&startStopLock);

exit = false;
start();

while (!running)
usleep(5000);
startStopWait.wait(locker.mutex());
}
DBG_SM("Start", "end");
}
Expand All @@ -248,52 +247,29 @@ void SignalMonitor::Start()
void SignalMonitor::Stop()
{
DBG_SM("Stop", "begin");

QMutexLocker locker(&startStopLock);
exit = true;
if (running)
{
QMutexLocker locker(&startStopLock);
if (running)
{
exit = true;
wait();
}
locker.unlock();
wait();
}
DBG_SM("Stop", "end");
}

/** \fn SignalMonitor::Kick()
* \brief Wake up monitor thread, and wait for
* UpdateValue() to execute once.
*/
void SignalMonitor::Kick()
{
update_done = false;

//pthread_kill(monitor_thread, SIGALRM);

while (!update_done)
usleep(50);
DBG_SM("Stop", "end");
}

/** \fn SignalMonitor::GetStatusList(bool)
* \brief Returns QStringList containing all signals and their current
/** \brief Returns QStringList containing all signals and their current
* values.
*
* This serializes the signal monitoring values so that they can
* be passed from a backend to a frontend.
*
* SignalMonitorValue::Parse(const QStringList&) will convert this
* to a vector of SignalMonitorValue instances.
*
* \param kick if true Kick() will be employed so that this
* call will not have to wait for the next signal
* monitoring event.
*/
QStringList SignalMonitor::GetStatusList(bool kick)
QStringList SignalMonitor::GetStatusList(void) const
{
if (kick && running)
Kick();
else if (!running)
UpdateValues();

QStringList list;
statusLock.lock();
list<<scriptStatus.GetName()<<scriptStatus.GetStatus();
Expand All @@ -305,90 +281,48 @@ QStringList SignalMonitor::GetStatusList(bool kick)
return list;
}

/** \fn SignalMonitor::MonitorLoop()
* \brief Basic signal monitoring loop
*/
void SignalMonitor::MonitorLoop()
/// \brief Basic signal monitoring loop
void SignalMonitor::MonitorLoop(void)
{
threadRegister("SignalMonitor");

QMutexLocker locker(&startStopLock);
running = true;
exit = false;
startStopWait.wakeAll();

while (!exit)
{
locker.unlock();

UpdateValues();

if (notify_frontend && capturecardnum>=0)
{
QStringList slist = GetStatusList(false);
QStringList slist = GetStatusList();
MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist);
gCoreContext->dispatch(me);
//VERBOSE(VB_GENERAL("sent SIGNAL");
}

usleep(update_rate * 1000);
locker.relock();
startStopWait.wait(locker.mutex(), update_rate);
}

// We need to send a last informational message because a
// signal update may have come in while we were sleeping
// if we are using the multithreaded dtvsignalmonitor.
locker.unlock();
if (notify_frontend && capturecardnum>=0)
{
QStringList slist = GetStatusList(false);
QStringList slist = GetStatusList();
MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist);
gCoreContext->dispatch(me);
}
running = false;
}

/** \fn SignalMonitor::WaitForLock(int)
* \brief Wait for a StatusSignaLock(int) of true.
*
* This can be called whether or not the signal
* monitoring thread has been started.
*
* \param timeout maximum time to wait in milliseconds.
* \return true if signal was acquired.
*/
bool SignalMonitor::WaitForLock(int timeout)
{
statusLock.lock();
if (-1 == timeout)
timeout = signalLock.GetTimeout();
statusLock.unlock();
if (timeout<0)
return false;

MythTimer t;
t.start();
if (running)
{
while (t.elapsed()<timeout && running)
{
Kick();

if (HasSignalLock())
return true;
locker.relock();

usleep(50);
}
if (!running)
return WaitForLock(timeout-t.elapsed());
}
else
{
while (t.elapsed()<timeout && !running)
{
UpdateValues();

if (HasSignalLock())
return true;
running = false;
startStopWait.wakeAll();

usleep(50);
}
if (running)
return WaitForLock(timeout-t.elapsed());
}
return false;
threadDeregister();
}

void SignalMonitor::AddListener(SignalMonitorListener *listener)
Expand Down
11 changes: 6 additions & 5 deletions mythtv/libs/libmythtv/signalmonitor.h
Expand Up @@ -10,6 +10,7 @@
using namespace std;

// Qt headers
#include <QWaitCondition>
#include <QThread>
#include <QMutex>

Expand Down Expand Up @@ -42,8 +43,6 @@ class SignalMonitor : protected QThread

virtual void Start();
virtual void Stop();
virtual void Kick();
virtual bool WaitForLock(int timeout = -1);

// // // // // // // // // // // // // // // // // // // // // // // //
// Flags // // // // // // // // // // // // // // // // // // // // //
Expand All @@ -62,7 +61,7 @@ class SignalMonitor : protected QThread
bool GetNotifyFrontend() const { return notify_frontend; }
/// \brief Returns milliseconds between signal monitoring events.
int GetUpdateRate() const { return update_rate; }
virtual QStringList GetStatusList(bool kick = true);
virtual QStringList GetStatusList(void) const;

/// \brief Returns true iff scriptStatus.IsGood() and signalLock.IsGood()
/// return true
Expand Down Expand Up @@ -197,8 +196,6 @@ class SignalMonitor : protected QThread
volatile uint64_t flags;
int update_rate;
uint minimum_update_rate;
bool running;
bool exit;
bool update_done;
bool notify_frontend;
bool tablemon;
Expand All @@ -215,6 +212,10 @@ class SignalMonitor : protected QThread
vector<SignalMonitorListener*> listeners;

QMutex startStopLock;
QWaitCondition startStopWait; // protected by startStopLock
volatile bool running; // protected by startStopLock
volatile bool exit; // protected by startStopLock

mutable QMutex statusLock;
mutable QMutex listenerLock;
};
Expand Down

0 comments on commit 6285825

Please sign in to comment.