Added mutex for critical regions in the decode process

This commit is contained in:
Jordan Sherer 2019-11-17 01:21:07 -05:00
parent 3fb66f888c
commit 6d6212a8c0
4 changed files with 70 additions and 58 deletions

View File

@ -43,6 +43,8 @@ bool Detector::reset ()
void Detector::clear () void Detector::clear ()
{ {
QMutexLocker mutex(&m_lock);
#if JS8_RING_BUFFER #if JS8_RING_BUFFER
// set index to roughly where we are in time (1ms resolution) // set index to roughly where we are in time (1ms resolution)
qint64 now (DriftingDateTime::currentMSecsSinceEpoch ()); qint64 now (DriftingDateTime::currentMSecsSinceEpoch ());
@ -64,6 +66,8 @@ void Detector::clear ()
qint64 Detector::writeData (char const * data, qint64 maxSize) qint64 Detector::writeData (char const * data, qint64 maxSize)
{ {
QMutexLocker mutex(&m_lock);
int ns=secondInPeriod(); int ns=secondInPeriod();
if(ns < m_ns) { // When ns has wrapped around to zero, restart the buffers if(ns < m_ns) { // When ns has wrapped around to zero, restart the buffers
dec_data.params.kin = 0; dec_data.params.kin = 0;

View File

@ -2,6 +2,8 @@
#define DETECTOR_HPP__ #define DETECTOR_HPP__
#include "AudioDevice.hpp" #include "AudioDevice.hpp"
#include <QScopedArrayPointer> #include <QScopedArrayPointer>
#include <QMutex>
#include <QMutexLocker>
// //
// output device that distributes data in predefined chunks via a signal // output device that distributes data in predefined chunks via a signal
@ -24,6 +26,7 @@ public:
// //
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned downSampleFactor = 4u, QObject * parent = 0); Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned downSampleFactor = 4u, QObject * parent = 0);
QMutex * getMutex(){ return &m_lock; }
unsigned period() const {return m_period;} unsigned period() const {return m_period;}
void setTRPeriod(unsigned p) {m_period=p;} void setTRPeriod(unsigned p) {m_period=p;}
bool reset () override; bool reset () override;
@ -55,6 +58,7 @@ private:
// data (a signals worth) at // data (a signals worth) at
// the input sample rate // the input sample rate
unsigned m_bufferPos; unsigned m_bufferPos;
QMutex m_lock;
}; };
#endif #endif

View File

@ -1496,8 +1496,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
// Don't block heartbeat's first run... // Don't block heartbeat's first run...
m_lastTxStartTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300); m_lastTxStartTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300);
// But do block the decoder's first run until the next transmit period // But do block the decoder's first run until 50% through next transmit period
m_lastTxStopTime = nextTransmitCycle(); m_lastTxStopTime = nextTransmitCycle().addSecs(-m_TRperiod/2);
int width = 75; int width = 75;
/* /*
@ -2687,7 +2687,7 @@ void MainWindow::dataSink(qint64 frames)
m_dateTime = DriftingDateTime::currentDateTimeUtc().toString ("yyyy-MMM-dd hh:mm"); m_dateTime = DriftingDateTime::currentDateTimeUtc().toString ("yyyy-MMM-dd hh:mm");
decode(); decode(k);
} }
QString MainWindow::save_wave_file (QString const& name, short const * data, int seconds, QString MainWindow::save_wave_file (QString const& name, short const * data, int seconds,
@ -3801,48 +3801,48 @@ void MainWindow::read_wav_file (QString const& fname)
m_nutc0=m_UTCdisk; m_nutc0=m_UTCdisk;
m_UTCdisk=fname.mid(i0+1,i1-i0-1).toInt(); m_UTCdisk=fname.mid(i0+1,i1-i0-1).toInt();
m_wav_future_watcher.setFuture (QtConcurrent::run ([this, fname] { m_wav_future_watcher.setFuture (QtConcurrent::run ([this, fname] {
auto basename = fname.mid (fname.lastIndexOf ('/') + 1); QMutexLocker lock(m_detector->getMutex());
auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive); auto basename = fname.mid (fname.lastIndexOf ('/') + 1);
// global variables and threads do not mix well, this needs changing auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive);
dec_data.params.nutc = 0; // global variables and threads do not mix well, this needs changing
if (pos > 0) dec_data.params.nutc = 0;
{ if (pos > 0)
if (pos == fname.indexOf ('_', -11) + 7) {
{ if (pos == fname.indexOf ('_', -11) + 7)
dec_data.params.nutc = fname.mid (pos - 6, 6).toInt (); {
} dec_data.params.nutc = fname.mid (pos - 6, 6).toInt ();
else }
{ else
dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt (); {
} dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt ();
} }
BWFFile file {QAudioFormat {}, fname};
bool ok=file.open (BWFFile::ReadOnly);
if(ok) {
auto bytes_per_frame = file.format ().bytesPerFrame ();
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))* bytes_per_frame;
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
std::min (max_bytes, file.size ()));
int frames_read = n / bytes_per_frame;
// zero unfilled remaining sample space
std::memset(&dec_data.d2[frames_read],0,max_bytes - n);
if (11025 == file.format ().sampleRate ()) {
short sample_size = file.format ().sampleSize ();
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
}
dec_data.params.kin = frames_read;
dec_data.params.newdat = 1;
} else {
dec_data.params.kin = 0;
dec_data.params.newdat = 0;
} }
BWFFile file {QAudioFormat {}, fname};
if(basename.mid(0,10)=="000000_000" && m_mode == "FT8") { bool ok=file.open (BWFFile::ReadOnly);
dec_data.params.nutc=15*basename.mid(10,3).toInt(); if(ok) {
auto bytes_per_frame = file.format ().bytesPerFrame ();
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))* bytes_per_frame;
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
std::min (max_bytes, file.size ()));
int frames_read = n / bytes_per_frame;
// zero unfilled remaining sample space
std::memset(&dec_data.d2[frames_read],0,max_bytes - n);
if (11025 == file.format ().sampleRate ()) {
short sample_size = file.format ().sampleSize ();
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
} }
dec_data.params.kin = frames_read;
dec_data.params.newdat = 1;
} else {
dec_data.params.kin = 0;
dec_data.params.newdat = 0;
}
})); if(basename.mid(0,10)=="000000_000" && m_mode == "FT8") {
dec_data.params.nutc=15*basename.mid(10,3).toInt();
}
}));
} }
void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
@ -3880,9 +3880,14 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
on_actionOpen_next_in_directory_triggered(); on_actionOpen_next_in_directory_triggered();
} }
void MainWindow::diskDat() //diskDat() void MainWindow::diskDat(){
{ QMutexLocker mutex(m_detector->getMutex());
if(dec_data.params.kin>0) {
if(dec_data.params.kin<=0) {
MessageBox::information_message(this, tr("No data read from disk. Wrong file format?"));
return;
}
int k; int k;
int kstep=m_FFTSize; int kstep=m_FFTSize;
m_diskData=true; m_diskData=true;
@ -3891,15 +3896,12 @@ void MainWindow::diskDat() //diskDat()
float bw=m_config.RxBandwidth(); float bw=m_config.RxBandwidth();
if(db > 0.0) degrade_snr_(dec_data.d2,&dec_data.params.kin,&db,&bw); if(db > 0.0) degrade_snr_(dec_data.d2,&dec_data.params.kin,&db,&bw);
for(int n=1; n<=m_hsymStop; n++) { // Do the waterfall spectra for(int n=1; n<=m_hsymStop; n++) { // Do the waterfall spectra
k=(n+1)*kstep; k=(n+1)*kstep;
if(k > dec_data.params.kin) break; if(k > dec_data.params.kin) break;
dec_data.params.npts8=k/8; dec_data.params.npts8=k/8;
dataSink(k); dataSink(k);
qApp->processEvents(); //Update the waterfall qApp->processEvents(); //Update the waterfall
} }
} else {
MessageBox::information_message(this, tr("No data read from disk. Wrong file format?"));
}
} }
//Delete ../save/*.wav //Delete ../save/*.wav
@ -4036,9 +4038,8 @@ bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurren
* try decoding * try decoding
* @return true if the decoder was activated, false otherwise * @return true if the decoder was activated, false otherwise
*/ */
bool MainWindow::decode(){ bool MainWindow::decode(qint32 k){
static int k0 = 9999999; static int k0 = 9999999;
int k = dec_data.params.kin;
int kZero = k0; int kZero = k0;
k0 = k; k0 = k;
@ -4406,7 +4407,10 @@ bool MainWindow::decodeProcessQueue(qint32 *pSubmode){
* copy the dec_data structure to shared memory and * copy the dec_data structure to shared memory and
* remove the lock file to start the decoding process * remove the lock file to start the decoding process
*/ */
void MainWindow::decodeStart(){ void MainWindow::decodeStart(){
// critical section
QMutexLocker mutex(m_detector->getMutex());
if(m_decoderBusy){ if(m_decoderBusy){
if(JS8_DEBUG_DECODE) qDebug() << "--> decoder cannot start...busy (busy flag)"; if(JS8_DEBUG_DECODE) qDebug() << "--> decoder cannot start...busy (busy flag)";
return; return;
@ -6466,7 +6470,7 @@ bool MainWindow::isMessageQueuedForTransmit(){
} }
bool MainWindow::isInDecodeDelayThreshold(int ms){ bool MainWindow::isInDecodeDelayThreshold(int ms){
if(m_lastTxStopTime.isNull()){ if(!m_lastTxStopTime.isValid() || m_lastTxStopTime.isNull()){
return false; return false;
} }

View File

@ -230,7 +230,7 @@ private slots:
void on_actionSpecial_mouse_commands_triggered(); void on_actionSpecial_mouse_commands_triggered();
void on_actionSolve_FreqCal_triggered(); void on_actionSolve_FreqCal_triggered();
void on_actionCopyright_Notice_triggered(); void on_actionCopyright_Notice_triggered();
bool decode(); bool decode(qint32 k);
bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle); bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle);
bool decodeEnqueueReady(qint32 k, qint32 k0); bool decodeEnqueueReady(qint32 k, qint32 k0);
bool decodeProcessQueue(qint32 *pSubmode); bool decodeProcessQueue(qint32 *pSubmode);