I wrapped a boost intrusive list with mutex to make it thread safe, to be used as a producer/consumer queue.
But on windows (MSVC 14) it's really slow, after profiling, 95% of time is spent idle, mainly on push()
and waint_and_pop()
methods.
I only have 1 producer and 2 producer/consumer threads.
Any suggestions to make this faster?
#ifndef INTRUSIVE_CONCURRENT_QUEUE_HPP
#define INTRUSIVE_CONCURRENT_QUEUE_HPP
#include <thread>
#include <mutex>
#include <condition_variable>
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
template<typename Data>
class intrusive_concurrent_queue
{
protected:
list<Data, constant_time_size<false> > the_queue;
mutable std::mutex the_mutex;
std::condition_variable the_condition_variable;
public:
void push(Data * data)
{
std::unique_lock<std::mutex> lock(the_mutex);
the_queue.push_back(*data);
lock.unlock();
the_condition_variable.notify_one();
}
bool empty() const
{
std::unique_lock<std::mutex> lock(the_mutex);
return the_queue.empty();
}
size_t unsafe_size() const
{
return the_queue.size();
}
size_t size() const
{
std::unique_lock<std::mutex> lock(the_mutex);
return the_queue.size();
}
Data* try_pop()
{
Data* popped_ptr;
std::unique_lock<std::mutex> lock(the_mutex);
if(the_queue.empty())
{
return nullptr;
}
popped_ptr= & the_queue.front();
the_queue.pop_front();
return popped_ptr;
}
Data* wait_and_pop(const bool & exernal_stop = false)
{
Data* popped_ptr;
std::unique_lock<std::mutex> lock(the_mutex);
the_condition_variable.wait(lock,[&]{ return ! ( the_queue.empty() | exernal_stop ) ; });
if ( exernal_stop){
return nullptr;
}
popped_ptr=&the_queue.front();
the_queue.pop_front();
return popped_ptr;
}
intrusive_concurrent_queue<Data> & operator=(intrusive_concurrent_queue<Data>&& origin)
{
this->the_queue = std::move(the_queue);
return *this;
}
};
#endif // !INTRUSIVE_CONCURRENT_QUEUE_HPP
Try removing the lock from the methods and lock the whole data structure when you do things with it.