2009-05-22 26 views
5

Necesito construir un sistema de trabajadores (representados como hilos) y (múltiples) colas. Los trabajos individuales están esperando en una de las colas y espera a que un hilo de trabajo los procese. Cada trabajador puede procesar trabajos solo desde algunas de las colas. Sin espera de giro. C/C++, pthreads, estándar POSIX.C++ - hilos y múltiples colas

El problema para mí es la cuestión de "múltiples colas". Sé cómo implementar esto con una sola cola. Los trabajadores deben esperar en todas las colas que pueden procesar (espere CUALQUIERA de ellas).

En Windows utilizaría WaitForMultipleObjects, pero esto debe ser multiplataforma.

No deseo ningún código en particular para esto, solo una pista o una descripción del modelo que debo usar. Gracias por adelantado.

+0

¿Puedes usar boost en absoluto? – PiNoYBoY82

Respuesta

4

Lo que puedes hacer es usar un condition variable. Haga que sus subprocesos de trabajo esperen una variable de condición. Cuando se agrega un trabajo a cualquiera de las colas de trabajos, indique la variable de condición. Luego, cuando el hilo de trabajo se despierta, comprueba las colas que está esperando. Si alguno de ellos tiene un trabajo, quita ese trabajo de la cola. De lo contrario, vuelve a esperar en la variable de condición. Esperar en una variable de condición pone el hilo en modo de suspensión, por lo que no consume tiempo de CPU.

Por supuesto, no hace falta decir que debe proteger todos los accesos a las colas de trabajos con un mutex (por ejemplo, pthread_mutex_t).

+0

Buena idea, pero esto activará todos los subprocesos de trabajo al agregar un trabajo a una cola vacía. Supongo que lo haré de esta manera de todos modos, pero ¿hay alguna manera de despertar solo el hilo "correcto" (e idealmente solo uno de todos los hilos correctos)? –

+0

pthread_cond_signal() despertará "al menos un" subproceso esperando en la variable de condición, mientras que pthread_cond_broadcast() activará todos los subprocesos. En teoría, pthread_cond_signal() solo debería activar un hilo la mayor parte del tiempo, pero no sé si eso es cierto o no en la práctica. –

+0

Pero en su solución I * need * para activar todos los hilos, porque un trabajo podría estar en una cola que el * one * trabajador no procesa. –

1

Si no hay demasiados trabajadores para cada cola, puede crear una variable de condición para cada trabajador.

0

Lo que haría sería utilizar boost :: asio para poner en cola datos para que sus múltiples hilos puedan tener éxito. Puede pasar una referencia a la cola mediante el comando de publicación y hacer que el proceso de subprocesos sea el adecuado.

0

En lugar de tener un bloqueo separado para cada cola, ¿por qué no tener un bloqueo para todas las colas?

  1. Espera en la cerradura
  2. Obtener el bloqueo
  3. quitar de la cola desde cualquier cola de
  4. Libere el bloqueo
  5. procesar el artículo quitadas de la cola
  6. Goto paso 1

Suponiendo que La demo dequeue toma un tiempo insignificante (por lo que la cerradura solo se lleva a cabo por un tiempo insignificante) allí puede no ser necesario más de un bloqueo.

+0

No creo que eso funcione. Un trabajador solo procesa trabajos desde una cola específica. Si hay un único trabajo en una cola "mala", el trabajador estará ocupado, esperando hasta que otro trabajador acepte el trabajo. –

0

Podría hacer algo como esto: cada trabajo tiene una "cola" asociada a él. Ejemplo:

Supongamos que tiene 2 colas. Sus trabajos podían decir:

job[0].queue = 1; /* That job is in queue 1 */ 
job[1].queue = 1; 
job[2].queue = 2; /* this job is in queue 2 */ 
... 
etc 

Así entonces usted tiene su "bolsa de hilos". Un hilo simplemente escoge un trabajo, digamos, trabajo [2]. Si ese subproceso solo puede procesar trabajos de la cola 1, vuelve a colocar esa tarea en la lista de espera y elige un trabajo diferente.

De modo que cada subproceso sabe qué colas tiene permiso para procesar, y cuando elige un trabajo, se asegura de que el campo "queue" del trabajo coincida. Si no lo hace, elige un trabajo diferente.

(esto es en muchos sentidos cómo funciona la programación de procesos en Linux en varios núcleos. Cada proceso tiene una máscara de bits que indica en qué procesadores puede ejecutarse, y luego el procesador se asegura de que se "permite" ejecutar ese proceso antes de hacerlo)

5

¿Qué tal:.

  • todos los subprocesos de trabajo espera en un semáforo
  • cuando se añade nada a la cola, el semáforo se incrementa, lo que despierta un solo hilo
  • la hilo chec ks las colas que está interesada en los procesos, uno de ellos y se remonta a la espera en el semáforo

Tendrá mutex adicional (es) de control de lectura real & escrituras en las colas.

+1

+1 Iré con Neil en este :) – ralphtheninja

0

He estado pensando en esto recientemente y la única idea que podría surgir es (suponiendo que tenga colas seguras para subprocesos) que solo haya varios subprocesos que atiendan una sola cola.

Luego puede tener uno o más trabajos produciendo subprocesos agregando trabajos a una sola cola y uno o más subprocesos de trabajo bloqueándose en la cola hasta que encuentren algo que procesar.

Si alguna vez tiene varias colas que varios subprocesos de trabajo tienen que sondear, una solución podría ser agregar un subproceso adicional para cada cola y una cola adicional. Los subprocesos adicionales se bloquean en su propia cola única, pero simplemente reenvían trabajos a la cola adicional. Ahora el hilo de trabajo existente vuelve al bloqueo en una sola cola.