2014-11-16 16:51:45 -05:00
|
|
|
#include "CubicSDRDefs.h"
|
|
|
|
#include <vector>
|
|
|
|
|
2014-12-01 18:59:07 -05:00
|
|
|
#ifdef __APPLE__
|
2014-12-11 19:07:21 -05:00
|
|
|
#include <pthread.h>
|
2014-12-01 18:59:07 -05:00
|
|
|
#endif
|
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
#include "DemodulatorPreThread.h"
|
2015-01-11 17:08:16 -05:00
|
|
|
#include "CubicSDR.h"
|
2014-12-16 18:27:02 -05:00
|
|
|
|
2015-11-17 19:32:47 -05:00
|
|
|
DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL), cModem(nullptr), cModemKit(nullptr)
|
2015-07-30 00:28:53 -04:00
|
|
|
{
|
2015-07-21 00:59:18 -04:00
|
|
|
initialized.store(false);
|
2014-11-26 22:29:23 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
freqShifter = nco_crcf_create(LIQUID_VCO);
|
|
|
|
shiftFrequency = 0;
|
2014-11-27 22:13:21 -05:00
|
|
|
|
2014-11-30 23:33:55 -05:00
|
|
|
workerQueue = new DemodulatorThreadWorkerCommandQueue;
|
|
|
|
workerResults = new DemodulatorThreadWorkerResultQueue;
|
2015-07-30 19:30:46 -04:00
|
|
|
|
|
|
|
workerThread = new DemodulatorWorkerThread();
|
|
|
|
workerThread->setInputQueue("WorkerCommandQueue",workerQueue);
|
|
|
|
workerThread->setOutputQueue("WorkerResultQueue",workerResults);
|
2014-11-26 21:05:19 -05:00
|
|
|
}
|
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
void DemodulatorPreThread::initialize() {
|
2014-11-26 21:05:19 -05:00
|
|
|
initialized = false;
|
|
|
|
|
2015-01-11 17:08:16 -05:00
|
|
|
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
|
2015-11-16 23:49:54 -05:00
|
|
|
// audioResampleRatio = (double) (params.audioSampleRate) / (double) params.bandwidth;
|
2014-11-26 21:05:19 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
float As = 60.0f; // stop-band attenuation [dB]
|
2014-11-16 16:51:45 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
|
2015-11-16 23:49:54 -05:00
|
|
|
// audioResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
|
|
|
// stereoResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
2014-12-26 21:55:13 -05:00
|
|
|
|
2015-03-15 21:02:26 -04:00
|
|
|
// Stereo filters / shifters
|
2015-11-16 23:49:54 -05:00
|
|
|
// double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate);
|
|
|
|
// float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition
|
|
|
|
// float mu = 0.0f; // fractional timing offset
|
|
|
|
//
|
|
|
|
// if (firStereoCutoff < 0) {
|
|
|
|
// firStereoCutoff = 0;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (firStereoCutoff > 0.5) {
|
|
|
|
// firStereoCutoff = 0.5;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// unsigned int h_len = estimate_req_filter_len(ft, As);
|
|
|
|
// float *h = new float[h_len];
|
|
|
|
// liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h);
|
|
|
|
//
|
|
|
|
// firStereoLeft = firfilt_rrrf_create(h, h_len);
|
|
|
|
// firStereoRight = firfilt_rrrf_create(h, h_len);
|
2015-03-15 21:02:26 -04:00
|
|
|
|
2015-06-05 00:28:32 -04:00
|
|
|
// stereo pilot filter
|
2015-11-16 23:49:54 -05:00
|
|
|
// float bw = params.bandwidth;
|
|
|
|
// if (bw < 100000.0) {
|
|
|
|
// bw = 100000.0;
|
|
|
|
// }
|
|
|
|
// unsigned int order = 5; // filter order
|
|
|
|
// float f0 = ((double) 19000 / bw);
|
|
|
|
// float fc = ((double) 19500 / bw);
|
|
|
|
// float Ap = 1.0f;
|
|
|
|
// As = 60.0f;
|
|
|
|
// iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2014-11-26 21:05:19 -05:00
|
|
|
initialized = true;
|
2015-01-03 17:07:39 -05:00
|
|
|
lastParams = params;
|
2014-11-16 16:51:45 -05:00
|
|
|
}
|
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
DemodulatorPreThread::~DemodulatorPreThread() {
|
2014-11-16 16:51:45 -05:00
|
|
|
}
|
|
|
|
|
2015-07-29 20:57:02 -04:00
|
|
|
void DemodulatorPreThread::run() {
|
2014-12-16 20:33:44 -05:00
|
|
|
#ifdef __APPLE__
|
2014-12-18 20:11:25 -05:00
|
|
|
pthread_t tID = pthread_self(); // ID of this thread
|
2014-12-28 05:13:46 -05:00
|
|
|
int priority = sched_get_priority_max( SCHED_FIFO) - 1;
|
2014-12-29 00:24:10 -05:00
|
|
|
sched_param prio = {priority}; // scheduling priority of thread
|
2014-12-18 20:11:25 -05:00
|
|
|
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
2014-12-01 18:59:07 -05:00
|
|
|
#endif
|
2014-11-22 22:17:33 -05:00
|
|
|
|
2014-11-26 21:05:19 -05:00
|
|
|
if (!initialized) {
|
|
|
|
initialize();
|
|
|
|
}
|
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
std::cout << "Demodulator preprocessor thread started.." << std::endl;
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-07-29 22:52:54 -04:00
|
|
|
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
|
|
|
|
|
2015-07-28 22:14:48 -04:00
|
|
|
ReBuffer<DemodulatorThreadPostIQData> buffers;
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-07-30 00:28:53 -04:00
|
|
|
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
|
2015-07-30 19:30:46 -04:00
|
|
|
iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput");
|
2015-07-30 00:28:53 -04:00
|
|
|
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
|
|
|
commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue");
|
2015-07-29 22:52:54 -04:00
|
|
|
|
2014-12-24 03:03:34 -05:00
|
|
|
std::vector<liquid_float_complex> in_buf_data;
|
|
|
|
std::vector<liquid_float_complex> out_buf_data;
|
2015-02-23 00:44:04 -05:00
|
|
|
// liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations
|
|
|
|
// bool carrySampleFlag = false;
|
2014-12-24 03:03:34 -05:00
|
|
|
|
2014-11-23 19:39:27 -05:00
|
|
|
while (!terminated) {
|
2014-12-22 23:27:52 -05:00
|
|
|
DemodulatorThreadIQData *inp;
|
2015-01-03 17:07:39 -05:00
|
|
|
iqInputQueue->pop(inp);
|
2014-11-16 16:51:45 -05:00
|
|
|
|
2014-11-30 23:33:55 -05:00
|
|
|
bool bandwidthChanged = false;
|
2015-01-11 17:08:16 -05:00
|
|
|
bool rateChanged = false;
|
|
|
|
DemodulatorThreadParameters tempParams = params;
|
2014-11-30 23:33:55 -05:00
|
|
|
|
2014-11-26 21:05:19 -05:00
|
|
|
if (!commandQueue->empty()) {
|
|
|
|
while (!commandQueue->empty()) {
|
|
|
|
DemodulatorThreadCommand command;
|
|
|
|
commandQueue->pop(command);
|
|
|
|
switch (command.cmd) {
|
2014-11-30 23:33:55 -05:00
|
|
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH:
|
2015-01-04 17:11:20 -05:00
|
|
|
if (command.llong_value < 1500) {
|
|
|
|
command.llong_value = 1500;
|
2014-11-26 21:05:19 -05:00
|
|
|
}
|
2015-01-11 17:08:16 -05:00
|
|
|
if (command.llong_value > params.sampleRate) {
|
|
|
|
tempParams.bandwidth = params.sampleRate;
|
|
|
|
} else {
|
|
|
|
tempParams.bandwidth = command.llong_value;
|
2014-11-26 21:05:19 -05:00
|
|
|
}
|
2014-11-30 23:33:55 -05:00
|
|
|
bandwidthChanged = true;
|
2014-11-26 21:05:19 -05:00
|
|
|
break;
|
2014-11-30 23:33:55 -05:00
|
|
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY:
|
2015-03-15 21:02:26 -04:00
|
|
|
params.frequency = tempParams.frequency = command.llong_value;
|
|
|
|
break;
|
|
|
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE:
|
|
|
|
tempParams.audioSampleRate = (int)command.llong_value;
|
|
|
|
rateChanged = true;
|
2014-11-27 22:13:21 -05:00
|
|
|
break;
|
2015-01-20 19:13:49 -05:00
|
|
|
default:
|
|
|
|
break;
|
2014-11-26 21:05:19 -05:00
|
|
|
}
|
|
|
|
}
|
2015-01-11 17:08:16 -05:00
|
|
|
}
|
|
|
|
|
2015-01-23 02:09:37 -05:00
|
|
|
if (inp->sampleRate != tempParams.sampleRate && inp->sampleRate) {
|
2015-01-11 17:08:16 -05:00
|
|
|
tempParams.sampleRate = inp->sampleRate;
|
|
|
|
rateChanged = true;
|
|
|
|
}
|
2014-11-26 21:05:19 -05:00
|
|
|
|
2015-01-11 17:08:16 -05:00
|
|
|
if (bandwidthChanged || rateChanged) {
|
|
|
|
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS);
|
|
|
|
command.sampleRate = tempParams.sampleRate;
|
|
|
|
command.audioSampleRate = tempParams.audioSampleRate;
|
|
|
|
command.bandwidth = tempParams.bandwidth;
|
|
|
|
command.frequency = tempParams.frequency;
|
2014-11-30 23:33:55 -05:00
|
|
|
|
2015-01-11 17:08:16 -05:00
|
|
|
workerQueue->push(command);
|
2014-11-26 21:05:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!initialized) {
|
2015-10-14 00:54:48 -04:00
|
|
|
inp->decRefCount();
|
2014-11-26 21:05:19 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-11-27 22:13:21 -05:00
|
|
|
// Requested frequency is not center, shift it into the center!
|
2015-03-26 22:45:52 -04:00
|
|
|
if ((params.frequency - inp->frequency) != shiftFrequency || rateChanged) {
|
|
|
|
shiftFrequency = params.frequency - inp->frequency;
|
2015-10-14 00:54:48 -04:00
|
|
|
if (abs(shiftFrequency) <= (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
|
|
|
nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) inp->sampleRate)));
|
2014-11-27 22:13:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-14 00:54:48 -04:00
|
|
|
if (abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) {
|
|
|
|
inp->decRefCount();
|
2014-11-27 22:13:21 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-12-24 01:28:33 -05:00
|
|
|
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
2014-12-26 16:15:35 -05:00
|
|
|
std::vector<liquid_float_complex> *data = &inp->data;
|
2015-01-11 17:08:16 -05:00
|
|
|
if (data->size() && (inp->sampleRate == params.sampleRate)) {
|
2014-12-26 16:15:35 -05:00
|
|
|
int bufSize = data->size();
|
2014-12-16 18:27:02 -05:00
|
|
|
|
2014-12-24 03:03:34 -05:00
|
|
|
if (in_buf_data.size() != bufSize) {
|
|
|
|
if (in_buf_data.capacity() < bufSize) {
|
|
|
|
in_buf_data.reserve(bufSize);
|
|
|
|
out_buf_data.reserve(bufSize);
|
|
|
|
}
|
|
|
|
in_buf_data.resize(bufSize);
|
|
|
|
out_buf_data.resize(bufSize);
|
|
|
|
}
|
2014-11-27 22:13:21 -05:00
|
|
|
|
2014-12-28 05:13:46 -05:00
|
|
|
in_buf_data.assign(inp->data.begin(), inp->data.end());
|
2014-12-26 16:15:35 -05:00
|
|
|
|
2014-12-24 03:03:34 -05:00
|
|
|
liquid_float_complex *in_buf = &in_buf_data[0];
|
|
|
|
liquid_float_complex *out_buf = &out_buf_data[0];
|
2014-12-16 18:27:02 -05:00
|
|
|
liquid_float_complex *temp_buf = NULL;
|
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (shiftFrequency != 0) {
|
|
|
|
if (shiftFrequency < 0) {
|
|
|
|
nco_crcf_mix_block_up(freqShifter, in_buf, out_buf, bufSize);
|
2014-11-27 22:13:21 -05:00
|
|
|
} else {
|
2015-01-03 17:07:39 -05:00
|
|
|
nco_crcf_mix_block_down(freqShifter, in_buf, out_buf, bufSize);
|
2014-11-27 22:13:21 -05:00
|
|
|
}
|
2014-12-14 20:23:52 -05:00
|
|
|
temp_buf = in_buf;
|
|
|
|
in_buf = out_buf;
|
|
|
|
out_buf = temp_buf;
|
2014-11-22 22:17:33 -05:00
|
|
|
}
|
2014-11-16 16:51:45 -05:00
|
|
|
|
2015-07-28 22:14:48 -04:00
|
|
|
DemodulatorThreadPostIQData *resamp = buffers.getBuffer();
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
int out_size = ceil((double) (bufSize) * iqResampleRatio) + 512;
|
|
|
|
|
|
|
|
if (resampledData.size() != out_size) {
|
|
|
|
if (resampledData.capacity() < out_size) {
|
|
|
|
resampledData.reserve(out_size);
|
|
|
|
}
|
|
|
|
resampledData.resize(out_size);
|
|
|
|
}
|
2014-12-16 20:33:44 -05:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
unsigned int numWritten;
|
|
|
|
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
|
|
|
|
|
|
|
|
resamp->setRefCount(1);
|
2015-02-23 00:44:04 -05:00
|
|
|
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
|
|
|
|
|
|
|
// bool uneven = (numWritten % 2 != 0);
|
|
|
|
|
|
|
|
// if (!carrySampleFlag && !uneven) {
|
|
|
|
// resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
|
|
|
// carrySampleFlag = false;
|
|
|
|
// } else if (!carrySampleFlag && uneven) {
|
|
|
|
// resamp->data.assign(resampledData.begin(), resampledData.begin() + (numWritten-1));
|
|
|
|
// carrySample = resampledData.back();
|
|
|
|
// carrySampleFlag = true;
|
|
|
|
// } else if (carrySampleFlag && uneven) {
|
|
|
|
// resamp->data.resize(numWritten+1);
|
|
|
|
// resamp->data[0] = carrySample;
|
|
|
|
// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*numWritten);
|
|
|
|
// carrySampleFlag = false;
|
|
|
|
// } else if (carrySampleFlag && !uneven) {
|
|
|
|
// resamp->data.resize(numWritten);
|
|
|
|
// resamp->data[0] = carrySample;
|
|
|
|
// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*(numWritten-1));
|
|
|
|
// carrySample = resampledData.back();
|
|
|
|
// carrySampleFlag = true;
|
|
|
|
// }
|
2015-02-16 13:49:04 -05:00
|
|
|
|
|
|
|
|
2014-11-16 16:51:45 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// resamp->audioResampleRatio = audioResampleRatio;
|
|
|
|
// resamp->audioResampler = audioResampler;
|
|
|
|
// resamp->audioSampleRate = params.audioSampleRate;
|
|
|
|
// resamp->stereoResampler = stereoResampler;
|
|
|
|
// resamp->firStereoLeft = firStereoLeft;
|
|
|
|
// resamp->firStereoRight = firStereoRight;
|
|
|
|
// resamp->iirStereoPilot = iirStereoPilot;
|
2015-11-17 19:32:47 -05:00
|
|
|
resamp->modem = cModem;
|
|
|
|
resamp->modemKit = cModemKit;
|
2015-01-11 17:08:16 -05:00
|
|
|
resamp->sampleRate = params.bandwidth;
|
2014-11-16 16:51:45 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
iqOutputQueue->push(resamp);
|
2014-11-16 16:51:45 -05:00
|
|
|
}
|
2014-12-01 02:10:36 -05:00
|
|
|
|
2014-12-24 03:03:34 -05:00
|
|
|
inp->decRefCount();
|
|
|
|
|
2015-08-24 07:25:04 -04:00
|
|
|
if (!terminated && !workerResults->empty()) {
|
2014-12-01 02:10:36 -05:00
|
|
|
while (!workerResults->empty()) {
|
|
|
|
DemodulatorWorkerThreadResult result;
|
|
|
|
workerResults->pop(result);
|
|
|
|
|
|
|
|
switch (result.cmd) {
|
|
|
|
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
|
2015-01-04 13:20:31 -05:00
|
|
|
msresamp_crcf_destroy(iqResampler);
|
|
|
|
|
2015-01-23 02:09:37 -05:00
|
|
|
if (result.iqResampler) {
|
|
|
|
iqResampler = result.iqResampler;
|
|
|
|
iqResampleRatio = result.iqResampleRatio;
|
|
|
|
}
|
2014-12-01 02:10:36 -05:00
|
|
|
|
2015-11-17 18:57:42 -05:00
|
|
|
// if (result.firStereoLeft) {
|
|
|
|
// firStereoLeft = result.firStereoLeft;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (result.firStereoRight) {
|
|
|
|
// firStereoRight = result.firStereoRight;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (result.iirStereoPilot) {
|
|
|
|
// iirStereoPilot = result.iirStereoPilot;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (result.audioResampler) {
|
|
|
|
// audioResampler = result.audioResampler;
|
|
|
|
// audioResampleRatio = result.audioResamplerRatio;
|
|
|
|
// stereoResampler = result.stereoResampler;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (result.audioSampleRate) {
|
|
|
|
// params.audioSampleRate = result.audioSampleRate;
|
|
|
|
// }
|
2014-12-01 02:10:36 -05:00
|
|
|
|
2015-11-17 19:32:47 -05:00
|
|
|
if (result.modem != nullptr) {
|
|
|
|
cModem = result.modem;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.modemKit != nullptr) {
|
|
|
|
cModemKit = result.modemKit;
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:02:26 -04:00
|
|
|
if (result.bandwidth) {
|
2015-01-23 02:09:37 -05:00
|
|
|
params.bandwidth = result.bandwidth;
|
|
|
|
}
|
2015-03-15 21:02:26 -04:00
|
|
|
|
|
|
|
if (result.sampleRate) {
|
2015-01-23 02:09:37 -05:00
|
|
|
params.sampleRate = result.sampleRate;
|
|
|
|
}
|
2015-01-20 19:13:49 -05:00
|
|
|
break;
|
|
|
|
default:
|
2014-12-01 02:10:36 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-16 16:51:45 -05:00
|
|
|
}
|
2014-11-30 17:11:29 -05:00
|
|
|
|
2015-07-28 22:14:48 -04:00
|
|
|
buffers.purge();
|
2015-07-29 22:52:54 -04:00
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED);
|
2014-12-11 19:07:21 -05:00
|
|
|
tCmd.context = this;
|
|
|
|
threadQueueNotify->push(tCmd);
|
2015-01-11 20:26:51 -05:00
|
|
|
std::cout << "Demodulator preprocessor thread done." << std::endl;
|
2014-11-16 16:51:45 -05:00
|
|
|
}
|
|
|
|
|
2014-12-16 18:27:02 -05:00
|
|
|
void DemodulatorPreThread::terminate() {
|
2014-11-23 19:39:27 -05:00
|
|
|
terminated = true;
|
2015-07-30 00:28:53 -04:00
|
|
|
DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue
|
|
|
|
iqInputQueue->push(inp);
|
2015-08-24 07:25:04 -04:00
|
|
|
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_NULL);
|
|
|
|
workerQueue->push(command);
|
2015-07-30 00:28:53 -04:00
|
|
|
workerThread->terminate();
|
2015-08-24 07:25:04 -04:00
|
|
|
t_Worker->join();
|
2015-07-30 00:28:53 -04:00
|
|
|
delete t_Worker;
|
2015-08-24 07:25:04 -04:00
|
|
|
delete workerThread;
|
|
|
|
delete workerResults;
|
|
|
|
delete workerQueue;
|
2014-11-23 19:39:27 -05:00
|
|
|
}
|