スレッドセーフではないため、スレッドセーフにする非常に単純なカプセル化std::vector
を構築しようとしていました。
これは非常にうまく機能しますが、小さな問題が 1 つあります。クラスのインスタンスが破棄され、別のスレッドがまだそのインスタンスからデータを読み取ろうとしている場合、スレッドは永久にハングし続けます。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();
}
編集定義を変更する必要があります。前に述べたように、コンテナは明らかにスレッドセーフではありません。命名法が誤解を招くものであっても、そうすることは想定されていません。確かに、まったくスレッドセーフではないことを行うことができます! ただし、コンテナーに書き込むスレッドは 1 つだけで、コンテナーから読み取るスレッドは 2 つまたは 3 つです。プロセスを停止しようとするまではうまくいきます。モニターの方が良かったと言わざるを得ません。しかし、時間がなくなり、それまでこれを変更することはできません。
どんなアイデアでも大歓迎です!ありがとうございます。