ブースト1.49で期待どおりに動作するために使用された、スレッドセーフなバウンド待ちキューの次のコードです。ただし、Boost 1.54に更新すると、コードは予期したとおりに実行されなくなります。すなわち、バッファが空(満杯)のとき、コンシューマスレッド(プロデューサスレッド)はm_not_empty(m_not_full)条件変数を永遠に待っていて、起きることはありません(プロデューサスレッドにはミューテックスがないためです)。ブースト1.54でスレッドセーフなバウンドキューがハングする
コードを破損する可能性のあるバージョン1.54にいくつかの変更がありますか?あるいは、私が見逃したコードに間違いがありますか?
#include <iostream>
#include <boost/circular_buffer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
template <class T>
class bounded_buffer {
public:
bounded_buffer(size_t capacity) {cb.set_capacity(capacity);}
void push(T item) {
boost::mutex::scoped_lock lock(m_mutex);
while (cb.full()) {
m_not_full.wait(lock);
}
cb.push_back(item);
lock.unlock();
m_not_empty.notify_one();
}
void pop(T &pItem) {
boost::mutex::scoped_lock lock(m_mutex);
while (cb.empty()) {
m_not_empty.wait(lock);
}
pItem = cb.front();
cb.pop_front();
lock.unlock();
m_not_full.notify_one();
}
private:
boost::mutex m_mutex;
boost::condition m_not_empty;
boost::condition m_not_full;
boost::circular_buffer<T> cb;
};
bounded_buffer<int> bb_int(4);
void producer() {
int i = 10;
for(int j=0; j<100; ++j) {
bb_int.push(i);
std::cout << "producer: " << i << std::endl;
i++;
}
}
void consumer() {
int i;
for(int j=0; j<100; ++j) {
bb_int.pop(i);
std::cout << "consumer: " << i << std::endl;
}
}
// Test code
int main() {
// Start the threads.
boost::thread consume(consumer);
boost::thread produce(producer);
// Wait for completion.
consume.join();
produce.join();
}
なぜ、_臨界セクション外の条件変数_を通知していませんか?両方の 'lock.unlock()'ステートメントを削除すると、何が起こったか試しましたか? – nosid
@nosid 'lock.unlock()'ステートメントを取り除くと何も変わりません – Alexey
これは掛かっていますよね? – Grzegorz