Implementación segura de subprocesos de memoria intermedia circular

Circular_buffer from boost library no es seguro para subprocesos. Así que envolví el objeto boost :: circular_buffer en una clase como se muestra a continuación. La exclusión mutua entre los hilos se logra (creo) mediante el uso de variables condicionales, un mutex y una adquisición / liberación de lockings. ¿Este hilo de implementación es seguro?

#include  #include  #include  #include  // Thread safe circular buffer template  class circ_buffer : private boost::noncopyable { public: typedef boost::mutex::scoped_lock lock; circ_buffer() {} circ_buffer(int n) {cb.set_capacity(n);} void send (T imdata) { lock lk(monitor); cb.push_back(imdata); buffer_not_empty.notify_one(); } T receive() { lock lk(monitor); while (cb.empty()) buffer_not_empty.wait(lk); T imdata = cb.front(); cb.pop_front(); return imdata; } void clear() { lock lk(monitor); cb.clear(); } int size() { lock lk(monitor); return cb.size(); } void set_capacity(int capacity) { lock lk(monitor); cb.set_capacity(capacity); } private: boost::condition buffer_not_empty; boost::mutex monitor; boost::circular_buffer cb; }; 

Editar Esto es ahora una clase de plantilla, que acepta un objeto de cualquier tipo (no solo el objeto cv::Mat ).

Sí.
Si bloquea todos los métodos públicos con el mismo locking, será seguro para los hilos.

Podría considerar utilizar lockings de lectura y escritura , que pueden tener un mejor rendimiento si tiene muchos lectores simultáneos.

Si no tiene muchos lectores, solo agregará gastos generales, pero puede valer la pena verificar la opción y las pruebas.

Creo que se ve bien, excepto que hay algunas copias inútiles de Mat made in send . No necesita lo nuevo, puede enviar directamente el argumento de send a su cb.

Su implementación es similar a la que muestra este blogger . Deberías leer ese blog para ver si te perdiste algo en tu implementación.

Si sus objetos Mat son caros de crear / copiar, debe evitar crearlos / copiarlos / eliminarlos continuamente. En su lugar, debe tener un grupo (también conocido como lista libre) de objetos Mat que continuamente se reciclan en algún tipo de architecture de canalización. Describo este tipo de architecture en esta respuesta a una pregunta relacionada.

En esa respuesta, sugerí usar una stack de locking para implementar el grupo, pero también podrías usar tu locking circular_buffer . La razón por la que sugerí una stack fue porque pensé que podría ser más compatible con la memoria caché, pero en realidad nunca medí para ver si podía hacer la diferencia.

Se ve bien a primera vista, excepto que no está usando la condición buffer_not_full en absoluto. Probablemente desee agregar un código similar al código buffer_not_empty .