2013-10-09 11 views
5

Następujący kod dla kolejki wątkowo bezpiecznej używanej do pracy zgodnie z oczekiwaniami w Boost 1.49. Jednak po aktualizacji do wersji Boost 1.54 kod nie działa już zgodnie z oczekiwaniami. Mianowicie, gdy bufor jest pusty (pełny), wątek konsumenta (wątek producenta) czeka na zawsze dla m_not_empty (m_not_full) zmiennej warunkowej i nigdy się nie budzi (myślę, że ponieważ wątek producenta nie ma muteksu).Kolejka powiązana z wątkami zawiesza się w wersji Boost 1.54

Czy są jakieś zmiany w wersji 1.54, które mogą złamać kod? A może są błędy w kodzie, które przeoczyłem?

#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(); 
} 
+0

Dlaczego _niewiadczysz o zmiennych warunkowych poza _krytycznymi sekcjami_? Czy próbowałeś, co się stanie, jeśli usuniesz obie instrukcje 'lock.unlock()'? – nosid

+0

@nosid Nic się nie zmienia, jeśli usuwam instrukcje 'lock.unlock()' – Alexey

+0

Wisi, prawda? – Grzegorz

Odpowiedz

2

Ok, znalazłem błąd. Skompilowałem kod w wersji release, ale został on powiązany z wersją debugującą pliku .lib. Zasadniczo w wersji Release I podłączyłem się do boost_thread-vc100-mt-gd-1_54.lib, ale powinno być ono połączone z boost_thread-vc100-mt-1_54.lib.

+0

To jest zwariowane zachowanie, stary! Dzięki za podpowiedź dla tych, którzy używają rzeczy MS. – Grzegorz

+0

@Grzegorz Tak, bez błędów związanych z prowadzeniem mnie, był to trudny do znalezienia błąd. Dzięki! – Alexey