Я пытаюсь сделать класс потоком безопасным с помощью мьютекса.
class Container
{
private:
vector<Foo> v;
boost::mutex m;
public:
void add(Foo item)
{
m.lock();
v.push_back(item);
m.unlock();
}
};
Проблема заключается в том, что boost::mutex
не копируется, поэтому это делает Container
не подлежащим копированию. Конечно, если я копирую Container
новый экземпляр, по-видимому, не должен содержать тот же мьютекс, что и старый, - он может иметь новый собственный мьютекс. Я мог написать собственные конструкторы копирования для Container
которые это делают, но на самом деле это сложный класс, и я не хочу этого делать. Итак, как насчет этого:
class CopyableMutex
{
private:
boost::mutex m;
public:
CopyableMutex() {}
CopyableMutex(CopyableMutex&) {} //don't copy, just create a new one
CopyableMutex& operator=(CopyableMutex&) {return *this;} //don't assign, keep it the same
void lock() {m.lock();}
void unlock() {m.unlock();}
};
... и затем заменить boost::mutex
в Container
с помощью CopyableMutex
.
Это отвратительная вещь? Если нет, то я изобретаю колесо - есть ли класс библиотеки, который делает это уже?
Да, это отвратительно.
Правильное решение проблемы - это специальный конструктор копирования и оператор присваивания для вашего контейнера.
Если класс "слишком сложный" для написания конструктора специальных копий, а затем отделяет безопасность потока от контейнера и имеет контейнер базового класса, который не содержит мьютекс и, возможно, производный класс "поточно-безопасный контейнер", который содержит мьютекс и имеет собственный конструктор копий и назначение op, которые просто вызывают для автоматически созданных базовых классов.
Container
, просто сделайте его закрытым вложенным классом (неправильное использование невозможно). В противном случае, укажите в названии, что это не копируемый мьютекс (не выполняетCopyableMutex a; CopyableMutex b(a); assert(a == b);
), а скорее create-new-on-invoking-copy -мьютекс (это ужасное имя;)