Merge pull request #82 from cjcliffe/threading_fixes

Threading fixes
This commit is contained in:
Charles J. Cliffe 2015-05-30 22:11:24 -04:00
commit a42cdea635
14 changed files with 43 additions and 52 deletions

View File

@ -180,7 +180,7 @@ RtAudio :: RtAudio( RtAudio::Api api )
getCompiledApi( apis ); getCompiledApi( apis );
for ( unsigned int i=0; i<apis.size(); i++ ) { for ( unsigned int i=0; i<apis.size(); i++ ) {
openRtApi( apis[i] ); openRtApi( apis[i] );
if ( rtapi_->getDeviceCount() ) break; if ( rtapi_ && rtapi_->getDeviceCount() ) break;
} }
if ( rtapi_ ) return; if ( rtapi_ ) return;

View File

@ -45,7 +45,6 @@ AppFrame::AppFrame() :
#endif #endif
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL); wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL); wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);

View File

@ -18,6 +18,7 @@ public:
int channels; int channels;
float peak; float peak;
std::vector<float> data; std::vector<float> data;
std::mutex busy_update;
AudioThreadInput() : AudioThreadInput() :
frequency(0), sampleRate(0), channels(0), peak(0) { frequency(0), sampleRate(0), channels(0), peak(0) {

View File

@ -61,6 +61,7 @@ public:
long long frequency; long long frequency;
long long sampleRate; long long sampleRate;
std::vector<liquid_float_complex> data; std::vector<liquid_float_complex> data;
std::mutex busy_rw;
DemodulatorThreadIQData() : DemodulatorThreadIQData() :
frequency(0), sampleRate(0) { frequency(0), sampleRate(0) {

View File

@ -310,6 +310,8 @@ void DemodulatorThread::threadMain() {
if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) { if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) {
ati_vis->busy_update.lock();
int num_vis = DEMOD_VIS_SIZE; int num_vis = DEMOD_VIS_SIZE;
if (stereo) { if (stereo) {
ati_vis->channels = 2; ati_vis->channels = 2;
@ -342,6 +344,8 @@ void DemodulatorThread::threadMain() {
// std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl; // std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl;
} }
ati_vis->busy_update.unlock();
audioVisOutputQueue->push(ati_vis); audioVisOutputQueue->push(ati_vis);
} }
if (!threadQueueControl->empty()) { if (!threadQueueControl->empty()) {

View File

@ -111,6 +111,9 @@ void SDRPostThread::threadMain() {
} }
if (iqVisualQueue.load() != NULL && iqVisualQueue.load()->empty()) { if (iqVisualQueue.load() != NULL && iqVisualQueue.load()->empty()) {
visualDataOut->busy_rw.lock();
if (visualDataOut->data.size() < num_vis_samples) { if (visualDataOut->data.size() < num_vis_samples) {
if (visualDataOut->data.capacity() < num_vis_samples) { if (visualDataOut->data.capacity() < num_vis_samples) {
visualDataOut->data.reserve(num_vis_samples); visualDataOut->data.reserve(num_vis_samples);
@ -121,6 +124,9 @@ void SDRPostThread::threadMain() {
visualDataOut->frequency = data_in->frequency; visualDataOut->frequency = data_in->frequency;
visualDataOut->sampleRate = data_in->sampleRate; visualDataOut->sampleRate = data_in->sampleRate;
visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples); visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples);
visualDataOut->busy_rw.unlock();
iqVisualQueue.load()->push(visualDataOut); iqVisualQueue.load()->push(visualDataOut);
} }

View File

@ -38,7 +38,7 @@ DataElement::DataElement() : data_type(DATA_NULL), data_val(NULL), data_size(0),
DataElement::~DataElement() { DataElement::~DataElement() {
if (data_val) { if (data_val) {
delete data_val; delete[] data_val;
data_val = NULL; data_val = NULL;
} }
} }
@ -1309,9 +1309,9 @@ long DataTree::getSerialized(char **ser_str, bool debug) {
memcpy(data_out + data_ptr, element_serialized, element_serialized_size); memcpy(data_out + data_ptr, element_serialized, element_serialized_size);
data_ptr += element_serialized_size; data_ptr += element_serialized_size;
delete de_name_index_serialized; delete[] de_name_index_serialized;
delete de_num_children_serialized; delete[] de_num_children_serialized;
delete element_serialized; delete[] element_serialized;
/* if it has children, traverse into them */ /* if it has children, traverse into them */
if (dn_stack.top()->hasAnother()) { if (dn_stack.top()->hasAnother()) {
@ -1360,8 +1360,8 @@ void DataTree::setSerialized(char *ser_str, bool debug) {
/* unserialization is a little less straightforward since we have to do a countdown of remaining children */ /* unserialization is a little less straightforward since we have to do a countdown of remaining children */
while (!dn_stack.empty()) { while (!dn_stack.empty()) {
int name_index; int name_index = 0;
int num_children; int num_children = 0;
/* pull the index of the name of this node */ /* pull the index of the name of this node */
de_name_index.setSerialized(ser_str + data_ptr); de_name_index.setSerialized(ser_str + data_ptr);
@ -1389,7 +1389,7 @@ void DataTree::setSerialized(char *ser_str, bool debug) {
/* end debug output */ /* end debug output */
/* name index >= 1 means it has a name */ /* name index >= 1 means it has a name */
if (name_index) { if (name_index >= 1) {
dn_stack.top()->setName(node_names[name_index - 1].c_str()); dn_stack.top()->setName(node_names[name_index - 1].c_str());
} else /* name is nil */ } else /* name is nil */
@ -1568,10 +1568,10 @@ bool DataTree::SaveToFile(const std::string& filename, bool compress, int compre
fout << flush; fout << flush;
fout.close(); fout.close();
delete hdr_serialized; free(hdr_serialized);
if (!compress) { if (!compress) {
delete serialized; free(serialized);
} else { } else {
delete compressed; delete compressed;
} }
@ -1630,8 +1630,8 @@ bool DataTree::LoadFromFile(const std::string& filename) {
setSerialized(serialized); setSerialized(serialized);
delete serialized; delete[] serialized;
delete hdr_serialized; delete[] hdr_serialized;
return true; return true;
} }

View File

@ -59,13 +59,6 @@ void ModeSelectorCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glContext->DrawBegin(); glContext->DrawBegin();
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
int demodType = 0;
if (demod) {
demodType = demod->getDemodulatorType();
}
int yval = getHoveredSelection(); int yval = getHoveredSelection();
for (int i = 0; i < numChoices; i++) { for (int i = 0; i < numChoices; i++) {

View File

@ -151,8 +151,6 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBColor color,
glEnd(); glEnd();
if (ofs * 2.0 < 16.0 / viewWidth) { if (ofs * 2.0 < 16.0 / viewWidth) {
ofs = 16.0 / viewWidth;
glColor4f(color.r, color.g, color.b, 0.2); glColor4f(color.r, color.g, color.b, 0.2);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glVertex3f(uxPos - ofsLeft, hPos + labelHeight, 0.0); glVertex3f(uxPos - ofsLeft, hPos + labelHeight, 0.0);
@ -241,8 +239,8 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBColor color, lon
glEnable(GL_BLEND); glEnable(GL_BLEND);
std::string demodStr; std::string demodStr = "";
GLFont::Align demodAlign; GLFont::Align demodAlign = GLFont::GLFONT_ALIGN_CENTER;
switch (demod->getDemodulatorType()) { switch (demod->getDemodulatorType()) {
case DEMOD_TYPE_FM: case DEMOD_TYPE_FM:

View File

@ -61,16 +61,23 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
if (!wxGetApp().getAudioVisualQueue()->empty()) { if (!wxGetApp().getAudioVisualQueue()->empty()) {
AudioThreadInput *demodAudioData; AudioThreadInput *demodAudioData;
wxGetApp().getAudioVisualQueue()->pop(demodAudioData); wxGetApp().getAudioVisualQueue()->pop(demodAudioData);
if (demodAudioData && demodAudioData->data.size()) {
if (waveform_points.size() != demodAudioData->data.size() * 2) { int iMax = demodAudioData?demodAudioData->data.size():0;
waveform_points.resize(demodAudioData->data.size() * 2);
if (demodAudioData && iMax) {
if (waveform_points.size() != iMax * 2) {
waveform_points.resize(iMax * 2);
} }
for (int i = 0, iMax = demodAudioData->data.size(); i < iMax; i++) { demodAudioData->busy_update.lock();
for (int i = 0; i < iMax; i++) {
waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f; waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f;
waveform_points[i * 2] = ((double) i / (double) iMax); waveform_points[i * 2] = ((double) i / (double) iMax);
} }
demodAudioData->busy_update.unlock();
setStereo(demodAudioData->channels == 2); setStereo(demodAudioData->channels == 2);
} else { } else {
std::cout << "Incoming Demodulator data empty?" << std::endl; std::cout << "Incoming Demodulator data empty?" << std::endl;

View File

@ -328,12 +328,6 @@ void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
} }
void TuningCanvas::OnMouseReleased(wxMouseEvent& event) { void TuningCanvas::OnMouseReleased(wxMouseEvent& event) {
GLint vp[4];
glGetIntegerv( GL_VIEWPORT, vp);
float viewHeight = (float) vp[3];
float viewWidth = (float) vp[2];
InteractiveCanvas::OnMouseReleased(event); InteractiveCanvas::OnMouseReleased(event);
int hExponent = hoverIndex - 1; int hExponent = hoverIndex - 1;

View File

@ -69,7 +69,6 @@ void TuningContext::DrawTuner(long long freq, int count, float displayPos, float
glGetIntegerv( GL_VIEWPORT, vp); glGetIntegerv( GL_VIEWPORT, vp);
float viewHeight = (float) vp[3]; float viewHeight = (float) vp[3];
float viewWidth = (float) vp[2];
freqStr.str(""); freqStr.str("");
freqStr << freq; freqStr << freq;
@ -118,8 +117,6 @@ void TuningContext::DrawTunerDigitBox(int index, int count, float displayPos, fl
glGetIntegerv( GL_VIEWPORT, vp); glGetIntegerv( GL_VIEWPORT, vp);
float viewHeight = (float) vp[3]; float viewHeight = (float) vp[3];
float viewWidth = (float) vp[2];
float pixelHeight = 2.0/viewHeight; float pixelHeight = 2.0/viewHeight;
glColor4f(1.0, 0,0,1); glColor4f(1.0, 0,0,1);
@ -187,12 +184,6 @@ bool bottom) {
} }
void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long center) { void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long center) {
GLint vp[4];
glGetIntegerv( GL_VIEWPORT, vp);
float viewHeight = (float) vp[3];
float viewWidth = (float) vp[2];
DrawTuner(freq, 11, -1.0, (1.0 / 3.0) * 2.0); DrawTuner(freq, 11, -1.0, (1.0 / 3.0) * 2.0);
DrawTuner(bw, 7, -1.0 + (2.25 / 3.0), (1.0 / 4.0) * 2.0); DrawTuner(bw, 7, -1.0 + (2.25 / 3.0), (1.0 / 4.0) * 2.0);
DrawTuner(center, 11, -1.0 + (2.0 / 3.0) * 2.0, (1.0 / 3.0) * 2.0); DrawTuner(center, 11, -1.0 + (2.0 / 3.0) * 2.0, (1.0 / 3.0) * 2.0);

View File

@ -110,6 +110,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
DemodulatorThreadIQData *iqData; DemodulatorThreadIQData *iqData;
wxGetApp().getIQVisualQueue()->pop(iqData); wxGetApp().getIQVisualQueue()->pop(iqData);
iqData->busy_rw.lock();
if (iqData && iqData->data.size()) { if (iqData && iqData->data.size()) {
setData(iqData); setData(iqData);
if (otherWaterfallCanvas) { if (otherWaterfallCanvas) {
@ -118,6 +120,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
} else { } else {
std::cout << "Incoming IQ data empty?" << std::endl; std::cout << "Incoming IQ data empty?" << std::endl;
} }
iqData->busy_rw.unlock();
} }
glContext->SetCurrent(*this); glContext->SetCurrent(*this);
@ -362,14 +366,12 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
bw = getBandwidth(); bw = getBandwidth();
bw = (long long) ceil((long double) bw * currentZoom); bw = (long long) ceil((long double) bw * currentZoom);
if (bw >= wxGetApp().getSampleRate()) { if (bw >= wxGetApp().getSampleRate()) {
bw = wxGetApp().getSampleRate();
disableView(); disableView();
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->disableView(); spectrumCanvas->disableView();
} }
} else { } else {
if (mouseTracker.mouseInView()) { if (mouseTracker.mouseInView()) {
long long freq = wxGetApp().getFrequency();
long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); long long mfreqA = getFrequencyAt(mouseTracker.getMouseX());
setBandwidth(bw); setBandwidth(bw);
long long mfreqB = getFrequencyAt(mouseTracker.getMouseX()); long long mfreqB = getFrequencyAt(mouseTracker.getMouseX());
@ -517,8 +519,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
} else { } else {
if (last_data_size + num_written < fft_size) { // priming if (last_data_size + num_written < fft_size) { // priming
unsigned int num_copy = fft_size; unsigned int num_copy = fft_size - last_data_size;
num_copy = fft_size - last_data_size;
if (num_written > num_copy) { if (num_written > num_copy) {
num_copy = num_written; num_copy = num_written;
} }

View File

@ -13,8 +13,6 @@ void WaterfallContext::Setup(int fft_size_in, int num_waterfall_lines_in) {
waterfall_lines = num_waterfall_lines_in; waterfall_lines = num_waterfall_lines_in;
fft_size = fft_size_in; fft_size = fft_size_in;
int half_fft_size = fft_size / 2;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (waterfall[i]) { if (waterfall[i]) {
glDeleteTextures(1, &waterfall[i]); glDeleteTextures(1, &waterfall[i]);
@ -23,7 +21,6 @@ void WaterfallContext::Setup(int fft_size_in, int num_waterfall_lines_in) {
waterfall_ofs[i] = waterfall_lines - 1; waterfall_ofs[i] = waterfall_lines - 1;
} }
// Stagger memory updates at half intervals for tiles
} }
void WaterfallContext::refreshTheme() { void WaterfallContext::refreshTheme() {
@ -72,7 +69,7 @@ void WaterfallContext::Draw(std::vector<float> &points) {
} }
waterfall_slice = new unsigned char[half_fft_size]; waterfall_slice = new unsigned char[half_fft_size];
delete waterfall_tex; delete[] waterfall_tex;
} }
if (activeTheme != ThemeMgr::mgr.currentTheme) { if (activeTheme != ThemeMgr::mgr.currentTheme) {
@ -107,7 +104,6 @@ void WaterfallContext::Draw(std::vector<float> &points) {
glGetIntegerv(GL_VIEWPORT, vp); glGetIntegerv(GL_VIEWPORT, vp);
float viewWidth = (float) vp[2]; float viewWidth = (float) vp[2];
float viewHeight = (float) vp[3];
// some bias to prevent seams at odd scales // some bias to prevent seams at odd scales
float half_pixel = 1.0 / viewWidth; float half_pixel = 1.0 / viewWidth;