thread safe boost intrusive list is slow

238 Views Asked by At

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
1

There are 1 best solutions below

1
On

Try removing the lock from the methods and lock the whole data structure when you do things with it.