Tengo un proceso de alta prioridad que necesita pasar datos a un proceso de baja prioridad. Escribí un buffer de anillo básico para manejar el paso de datos:buffer de anillo sin inversión de prioridad
class RingBuffer {
public:
RingBuffer(int size);
~RingBuffer();
int count() {return (size + end - start) % size;}
void write(char *data, int bytes) {
// some work that uses only buffer and end
end = (end + bytes) % size;
}
void read(char *data, int bytes) {
// some work that uses only buffer and start
start = (start + bytes) % size;
}
private:
char *buffer;
const int size;
int start, end;
};
Aquí está el problema. Supongamos que el proceso de baja prioridad tiene un oráculo que le dice exactamente la cantidad de datos que se deben leer, de modo que no es necesario llamar al count()
. Entonces (a menos que me falta algo) no hay problemas de concurrencia. Sin embargo, tan pronto como el hilo de baja prioridad necesite llamar al count()
(el hilo de alta prioridad podría querer llamarlo también para verificar si el buffer está demasiado lleno) existe la posibilidad de que el recuento matemático() o la actualización a el final no es atómico, presentando un error.
Podría poner un mutex alrededor de los accesos para iniciar y terminar, pero eso causaría la inversión de prioridad si el hilo de alta prioridad tiene que esperar al bloqueo adquirido por el hilo de baja prioridad.
Podría ser capaz de resolver algo usando operaciones atómicas, pero no conozco una buena biblioteca multiplataforma que las proporcione.
¿Existe un diseño estándar de buffer de anillo que evite estos problemas?
¿Tiene alguna restricciones sobre las plataformas utilizadas? –
@Peter Supongamos que x86 (donde las escrituras IIRC de 32 bits para las direcciones alineadas son atómicas) aunque cuanto más portátil, mejor. – user168715
Aquí hay una cola que opera principalmente sin esperas http://software.intel.com/en-us/articles/single-producer-single-consumer-queue/ –