2012-05-29 1 views
2

У меня проблемы с deque и boost :: mutex, я сделал простой пример, который будет компилироваться с ошибкой ниже.Не может быть Boost :: mutex в качестве частного члена класса при использовании с std :: deque?

Проблема в том, что я хочу иметь deque некоторого класса, который имеет один или несколько мьютексов как частный член. Хотя в настоящее время пример дает ошибку:

ошибка C2248: «повышение :: мьютекс :: семафор»: не может получить доступ к закрытому члену, объявленный в классе "подталкивание :: мьютекс

Я видел некоторые соответствующие должности, но так далеко мне не удалось решить эту конкретную проблему.

Любая помощь будет принята с благодарностью ...

#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; 
}; 
+1

Вы должны использовать тип блокировки с привязкой вместо вызова блокировки/разблокировки вручную –

ответ

3

Если вы не хотите писать конструкторы копирования, чтобы избежать копирования мьютекса, вместо этого вы можете использовать Pointer Container от Boost.

Например:

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

Теперь Deque ведет себя так же, как обычный дека, но он никогда не пытается копировать любые object экземпляров.

+0

Это работает и является очень прозрачным решением. Благодарю. – AlexS

3

Мьютексы не CopyConstructible, поэтому конструктор копирования вашего типа является плохо образован.

Вы можете указать пользовательский конструктор копирования, который не копирует мьютексы.

+0

Привет, я должен был упомянуть, что я уже понял это из сообщений, которые я прочитал, но как это можно решить? – AlexS

+0

Как выглядит пользовательский конструктор копирования? Я не понимаю. – AlexS

+0

Опуская копию мьютекса в специализированном конструкторе копирования, вы, возможно, избегаете одной проблемы и создаете другую. Что, если один поток приобрел блокировку, а другой что-то делает для 'deque', который требует копирования объекта? – Praetorian

2

Вы не можете копировать мьютексы, и вы также не можете копировать свой класс, содержащий мьютексы. В качестве альтернативы вы можете сделать Deque из unique_ptr с к классу

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

Это выглядит красиво, но похоже, что это не вариант под VS2008, только в новом STL, используя #include . Правильно ли это звучит? – AlexS

+0

@AlexS вы можете использовать boost :: shared_ptr в качестве решения стоп-кадра. Или, поскольку ваше использование объектов кажется довольно локализованным, необработанные указатели могут быть опцией. – juanchopanza

+0

@juanchopanza Спасибо, но если использовать boost, кажется, что обратное решение является самым простым. – AlexS

4
obj.push_back(object(1)); 

выше строка создает временный object экземпляр, который затем скопировать построенный в DEQUE элемент. Поскольку boost::mutex не копируется, компилятор не может синтезировать конструктор копии для object.

Если это единственное место, где вам нужно object быть скопировать построимые изменить заявление

obj.emplace_back(1); 

emplace_back вызывает экземпляр object будет построен на месте, вместо того, чтобы использовать конструкцию копирования.


Если у вас нет доступа к C++ 11 функций, изменить object класс к следующему:

#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; 
}; 

В VS2008 вы, возможно, придется использовать std::tr1::shared_ptr вместо этого.

Смежные вопросы