2010-07-19 7 views
5

Le pregunté a previous question sobre el código de productor/consumidor que era demasiado general (aunque las respuestas fueron ciertamente útiles). Así que tomé las sugerencias de un earlier SO question de otro autor y las convertí a C++ y realcé. Sin embargo, siempre estoy un poco preocupado por el código multiproceso, por lo que si alguien puede ver alguna mejora obvia, me encantaría saber de ellos.Cualquier problema obvio o mejoras para mi cola de consumidor productor

#include <pthread.h> 
#include <deque> 
#include <iostream> 

#include "boost/thread.hpp" 


class MyQueue 
{ 
protected: 
    boost::mutex mutex_; 
    boost::condition_variable condition_; 
    bool cancel_; 
    std::deque<int> data_; 

public: 
    MyQueue() : mutex_(), condition_(), cancel_(false), data_() 
    { 
    } 

    struct Canceled{}; 

    void push(int i) 
    { 
    boost::lock_guard<boost::mutex> l(mutex_); 
    if(cancel_) throw Canceled(); 
    data_.push_back(i); 
    condition_.notify_all(); 
    } 

    void pop(int & i) 
    { 
    boost::unique_lock<boost::mutex> l(mutex_); 
    while(! cancel_ && data_.size()==0) 
    { 
     condition_.wait(l); 
    } 
    if(cancel_) throw Canceled(); 

    assert(data_.size() != 0); 
    i = data_.front(); 
    data_.pop_front(); 
    } 

    void cancel() 
    { 
    boost::lock_guard<boost::mutex> l(mutex_); 
    if(cancel_) throw Canceled(); 
    cancel_ = true; 
    condition_.notify_all(); 
    } 
}; 


boost::mutex iomutex; 

void producer(MyQueue * q, const std::string & name) 
try 
{ 
    for(unsigned int i=0 ; i<20; ++i) 
    { 
    q->push(i); 
    boost::lock_guard<boost::mutex> l(iomutex); 
    std::cout<<name<<" PRODUCED "<<i<<std::endl; 
    } 

    sleep(1); 
    q->cancel(); 
    { 
    boost::lock_guard<boost::mutex> l(iomutex); 
    std::cout<<name<<" PRODUCER EXITING NORMALLY"<<std::endl; 
    } 
} 
catch(MyQueue::Canceled & c) 
{ 
    boost::lock_guard<boost::mutex> l(iomutex); 
    std::cout<<name<<" PRODUCER CANCLED "<<std::endl; 
} 

void consumer(MyQueue * q, const std::string & name) 
try 
{ 
    while(true) 
    { 
    int i; 
    q->pop(i); 
    boost::lock_guard<boost::mutex> l(iomutex); 
    std::cout<<name<<" CONSUMED "<<i<<std::endl; 
    } 
} 
catch(MyQueue::Canceled & c) 
{ 
    boost::lock_guard<boost::mutex> l(iomutex); 
    std::cout<<name<<" CONSUMER CANCLED "<<std::endl; 
} 

int main() 
{ 
    MyQueue q; 
    boost::thread pr1(producer, &q, "pro1"); 
    boost::thread pr2(producer, &q, "pro2"); 
    boost::thread cons1(consumer, &q, "con1"); 
    boost::thread cons2(consumer, &q, "con2"); 

    pr1.join(); 
    pr2.join(); 
    cons1.join(); 
    cons2.join(); 
} 

ACTUALIZACIÓN: Terminé usando una versión modificada del Anthony Williams' concurrent queue. Mi versión modificada se puede encontrar here.

Respuesta

5

Si le preocupan las posibles dificultades en su implementación, puede intentar utilizar Anthony Williams (mantenedor de la biblioteca Boost.Thread) excelente thread-safe, multiple-producer, multiple-consumer queue.

+0

+1, Ah, me había encontrado con esto antes. No tiene la capacidad de cancelar a los consumidores. Pero en realidad publiqué una modificación que (creo) permite cancelar. Estaba un poco nervioso acerca de usar una biblioteca de MT de alguien de quien no sabía nada ... sin embargo, como un respetado mantenedor de la biblioteca de hilos, parece probable que sepa lo que está haciendo. –

+0

Como la cola de Williams en realidad no gestiona los hilos del productor o del consumidor, la cancelación de los consumidores solo se puede hacer haciendo que revisen un indicador antes de intentar abrir la cola y/o interrumpirlos si es necesario. Ver http://www.boost.org/doc/libs/1_42_0/doc/html/thread/thread_management.html#thread.thread_management.interruption Tiendo a mantener ese aspecto de gestión de hilos independiente de la cola. – tmatth

+0

si manejamos la cancelación fuera de la cola, entonces el hilo de cancelación debe tener un control para cada posible hilo de lectura. Eso suena como un peor nivel de acoplamiento para mí. –

Cuestiones relacionadas