Как std::vector
не является потокобезопасным, я пытался построить очень простой инкапсуляция вокруг него, что делает его потокобезопасным.Release boost :: mutex from destructor
Это работает довольно хорошо, но есть одна небольшая проблема. Когда экземпляр класса разрушается, а другой поток все еще пытается прочитать данные из него, нить продолжает вешать навсегда в boost::mutex::scoped_lock lock(m_mutex);
Как я могу решить эту проблему? Лучше всего просто разблокировать мьютексы, чтобы нить, висящая в ней, могла продолжить выполнение. Я не определил деструктор, потому что до сих пор это не требовалось.
Здесь мой код. Обратите внимание, что существует больше способов, чем показано здесь, это упрощено.
template<class T>
class SafeVector
{
public:
SafeVector();
SafeVector(const SafeVector<T>& other);
unsigned int size() const;
bool empty() const;
void clear();
T& operator[] (const unsigned int& n);
T& front();
T& back();
void push_back(const T& val);
T pop_back();
void erase(int i);
typename std::vector<T>::const_iterator begin() const;
typename std::vector<T>::const_iterator end() const;
const SafeVector<T>& operator= (const SafeVector<T>& other);
protected:
mutable boost::mutex m_mutex;
std::vector<T> m_vector;
};
template<class T>
SafeVector<T>::SafeVector()
{
}
template<class T>
SafeVector<T>::SafeVector(const SafeVector<T>& other)
{
this->m_vector = other.m_vector;
}
template<class T>
unsigned int SafeVector<T>::size() const
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.size();
}
template<class T>
bool SafeVector<T>::empty() const
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.empty();
}
template<class T>
void SafeVector<T>::clear()
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.clear();
}
template<class T>
T& SafeVector<T>::operator[] (const unsigned int& n)
{
boost::mutex::scoped_lock lock(m_mutex);
return (this->m_vector)[n];
}
template<class T>
T& SafeVector<T>::front()
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.front();
}
template<class T>
T& SafeVector<T>::back()
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.back();
}
template<class T>
void SafeVector<T>::push_back(const T& val)
{
boost::mutex::scoped_lock lock(m_mutex);
return this->m_vector.push_back(val);
}
template<class T>
T SafeVector<T>::pop_back()
{
boost::mutex::scoped_lock lock(m_mutex);
T back = m_vector.back();
m_vector.pop_back();
return back;
}
template<class T>
void SafeVector<T>::erase(int i)
{
boost::mutex::scoped_lock lock(m_mutex);
this->m_vector.erase(m_vector.begin() + i);
}
template<class T>
typename std::vector<T>::const_iterator SafeVector<T>::begin() const
{
return m_vector.begin();
}
template<class T>
typename std::vector<T>::const_iterator SafeVector<T>::end() const
{
return m_vector.end();
}
Edit я должен изменить мое определение. Контейнер, очевидно, не является потокобезопасным, как указано выше. Он не должен этого делать - даже если номенклатура вводит в заблуждение. Уверен, что вы можете делать с ним все, что не является потокобезопасным! Но только один поток записывает в контейнер, 2 или 3 читает его. Он работает хорошо, пока я не попытаюсь остановить процесс. Я должен сказать, что монитор был бы лучше. Но время истекает, и я не могу изменить это до тех пор.
Любая идея оценивается! Спасибо и приветствую.
Я думаю, что у вас есть поточные вопросы на более высокий уровне. Похоже, что для потока 1 кажется ошибкой думать, что законно уничтожать объект, в который есть ссылка 2, и полагает, что он может читать из него. Что делать, если потоку 1 действительно удалось полностью уничтожить объект, а _then_ thread 2 попытался прочитать из него? –
Не будет ли конструктор копирования также блокировать * другой * вектор? –
Мне было бы интересно увидеть реализацию оператора присваивания копий. Было бы легко сделать это эффектно неправильно. –