2
votes

I'm having some trouble with deque and boost::mutex, I've made a simple example that will compile with the error below.

The problem is that I want to have a deque of some class which has one or more mutexes as a private member. Though currently the example gives an error:

error C2248: 'boost::mutex::mutex' : cannot access private member declared in class 'boost::mutex'

I have seen some related posts but so far I have not managed to solve this specific problem.

Any help would be greatly appreciated...

#include <iostream>  
#include <boost/thread.hpp>  
#include <deque>  

using namespace std;

class object {
public:
    void process(void)
    {
        m_mutex.lock();
        // do something
        a = a*10;
        m_mutex.unlock();
    }
    object(int v){  a = v; }        
private:
    int a;
    boost::mutex m_mutex;
};

int main(int argc, char* argv[])  
{
    deque<object> obj; 

    obj.push_back( object( 1 ) );
    obj.push_back( object( 2 ) );
    obj.push_back( object( 3 ) );

    obj.at(0).process();
    obj.at(1).process();
    obj.at(2).process();

    return 0;  
};
4
You should use a scoped lock type instead of calling lock/unlock manually - Jonathan Wakely

4 Answers

4
votes
obj.push_back( object( 1 ) );

The above line creates a temporary object instance which is then copy constructed into the deque element. Since boost::mutex is not copy constructible, the compiler cannot synthesize a copy constructor for object.

If that's the only place where you need object to be copy constructible change the statement to

obj.emplace_back( 1 );

emplace_back causes the object instance to be constructed in place, instead of using copy construction.


If you don't have access to C++11 features, change the object class to the following:

#include <memory>

class object {
public:
    void process(void)
    {
        m_mutex->lock();
        // do something
        a = a*10;
        m_mutex->unlock();
    }
    object(int v)
    : m_mutex( std::make_shared<boost::mutex>() )
    {  
      a = v; 
    }     

private:
    int a;
    std::shared_ptr<boost::mutex> m_mutex;
};

In VS2008 you may have to use std::tr1::shared_ptr instead.

3
votes

The mutex is not CopyConstructible, so your type's copy constructor is ill-formed.

You could provide a user-defined copy constructor which doesn't copy the mutex.

3
votes

If you don't want to bother writing copy constructors to avoid copying the mutex, you could instead use a Pointer Container from Boost.

For example:

#include <boost/ptr_container/ptr_deque.hpp>
...
boost::ptr_deque<object> obj;
obj.push_back(new object());
obj[0].process()
...

Now the deque behaves just like a normal deque but it never tries to copy any object instances.

2
votes

You can't copy mutexs and as such you also can't copy your class containing the mutex. As an alternative you can make a deque of unique_ptrs to your class

 std::deque<std::unique_ptr<object>> obj;