Тъй като std::vector
не е безопасен за нишки, аз се опитвах да създам много проста капсулация около него, което го прави безопасен за нишки.
Това работи доста добре, но има един малък проблем. Когато екземплярът на класа се унищожава и друга нишка все още се опитва да прочете данни от нея, нишката продължава да виси завинаги в boost::mutex::scoped_lock lock(m_mutex);
Как мога да разреша това? Най-добре е просто да отключите 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();
}
Редактиране Трябва да променя дефиницията си. Контейнерът очевидно не е безопасен за нишки, както беше посочено по-горе. Не трябва да го прави - дори номенклатурата да е подвеждаща. Разбира се, можете да правите неща с него, които изобщо не са безопасни за нишки! Но само една нишка пише в контейнера, 2 или 3 четат от нея. Работи добре, докато не опитам да спра процеса. Трябва да кажа, че монитор би бил по-добър. Но времето изтича и не мога да променя това дотогава.
Всяка идея се оценява! Благодаря и поздрави.
std::vector
не е безопасен за нишки поради причина. Безопасните за нишки контейнери обикновено са неизменни. Нещо повече, дори за обекти, безопасни за нишки (напр. std::atomic‹int› и самият boost::mutex) конструирането и унищожаването не са безопасни за нишки. - person Yakov Galka   schedule 14.01.2012A
, съхраняващ някои SafeVectors. Нишка (не същата, която създаде обектA
) променя данните в тези SafeVectors по време на цикъл. Друг чете от тях. Сега, когато искам да затворя целия процес, изглежда, че една нишка винаги виси в ключалката, всъщност предотвратявайкиA
да бъде унищожен. - person Atmocreations   schedule 14.01.2012<concurrent_vector>
, който е наличен във Visual Studio от 2010 IIRC. - person Xeo   schedule 15.01.2012