I am working on a real-time music application. Working with boost library as a newbie. I implemented a Producer/Consumer relationship with a protected SyncronizedQueue, actually I implemented the 18.11 and 18.12 sections of https://www.quantnet.com/cplusplus-multithreading-boost/. When parsing the midi input I get the following exception:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl
<boost::exception_detail::error_info_injector<boost::lock_error> >'
what(): boost::lock_error
Code for parsing input in producer:
RtMidiIn *midiin = new RtMidiIn();
std::vector<unsigned char> message;
int nBytes, i;
double stamp;
m_queue=queue;
// Check available ports.
unsigned int nPorts = midiin->getPortCount();
if ( nPorts == 0 ) {
std::cout << "No ports available!\n";
goto cleanup;
}
midiin->openPort( 1 );
// Don't ignore sysex, timing, or active sensing messages.
midiin->ignoreTypes( false, false, false );
// Install an interrupt handler function.
done = false;
(void) signal(SIGINT, finish);
// Periodically check input queue.
std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n";
while ( !done ) {
stamp = midiin->getMessage( &message );
nBytes = message.size();
if(nBytes>0){
if((message.size()!=1)&&((int)message.at(0)!=137)){
for ( i=0; i<nBytes; i++ )
std::cout << "Byte " << i << " = " << (int)message[i] << ", ";
if ( nBytes > 0 )
std::cout << "stamp = " << stamp << std::endl;
m_queue->Enqueue("asd");
}
}
}
it breaks on the first time it encounters:
m_queue->Enqueue("asd");
When trying to execute:
boost::unique_lock<boost::mutex> lock(m_mutex);
Any help appreciated!
EDIT1:
This is the SynchronizedQueue object. The exception is thrown when calling Enqueue().
template <typename T>
class SynchronizedQueue
{
private:
std::queue<T> m_queue; // Use STL queue to store data
mutable boost::mutex m_mutex; // The mutex to synchronise on
boost::condition_variable m_cond; // The condition to wait for
public:
// Add data to the queue and notify others
void Enqueue(const T& data)
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
// Add the data to the queue
m_queue.push(data);
// Notify others that data is ready
m_cond.notify_one();
} // Lock is automatically released here
// Get data from the queue. Wait for data if not available
T Dequeue()
{
// Acquire lock on the queue
boost::unique_lock<boost::mutex> lock(m_mutex);
//lock();
// When there is no data, wait till someone fills it.
// Lock is automatically released in the wait and obtained
// again after the wait
while (m_queue.size()==0) m_cond.wait(lock);
// Retrieve the data from the queue
T result=m_queue.front(); m_queue.pop();
return result;
} // Lock is automatically released here
};
most times, when I stumble over such an issue, it's that the mutex that got locked is already destroyed or wasn't constructed already. Are you sure, the queue, that you are passing to your parser, is already constructed, when the parser threads starts parsing? Or it might be, that the exit of a loop containing the queue as local variable stopped? Maybe you can do a quick test and add a d'tor to the queue and set a breakpoint there.
regards Torsten