3

I'm trying to implement a program that has a producer and N (N >= 1) workers. They communicate using a message queue. The idea is that the producer sends to the queue "tasks". The workers do a msgrcv() call to get a task and execute some code. After the worker accomplish the task it sends to the queue the result of the computation. The producer will get this message and save the results.

I'm using POSIX message queues and the producer and the workers work concurrently.

The problem behind this program is that exists a scenario that compromises the communication. Each message has a size of ~5000 bytes. The maximum queue size is ~16000 bytes in UNIX Systems, which is the case.

The scenario is: There are 3 tasks in the queue (5000*3 = 15000 bytes). Some worker get one message from the queue (now the queue has 10000 bytes). The worker starts executing the task and, due to the amount of bytes that a worker has to process in each task, the producer sends to the queue another message (the queue is now full). Now after the task is complete the worker tries to send the result to the queue and becomes blocked (the queue is full). The producer tries to send another task to the queue and becomes blocked too.

If I run this program with only one worker this scenario have a considerable probability to occur.

Does anyone have an idea to avoid this situation?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
David S.
  • 33
  • 1
  • 3
  • I'd consider using a message queuing mechanism without these limitations rather than using something which seems fundamentally unsuitable for your use case. (Unless you have a hard requirement to use POSIX MQs.) Maybe ZeroMQ – I believe it works as a lightweight embeddable library. – millimoose Nov 20 '11 at 23:13
  • Thank you for your quick answer. Yes in this case I have to use POSIX MQs. – David S. Nov 20 '11 at 23:16
  • Are you using multiple threads in one program or multiple processes? – Dmitri Nov 20 '11 at 23:43
  • 1
    Multiple processes. For being Specific i'm using one main process that launches the producer and the producer launches the workers. The producer creates the tasks after all the workers are launched. (it's not the best solution but it's a university work and the program needs to be constructed like this) – David S. Nov 20 '11 at 23:44

2 Answers2

1

If you can't change the queue size, number of queues to use, or use a different queuing API, then what about queuing less data?

You could place the actual data in shared memory objects or temporary files. Then instead of putting the data in the message, you'd put a file name or shared memory object name and possibly an offset in the message instead. The producer process can then clean it up after receiving the results.

It doesn't necessarily have to be shared memory or temporary files, but the idea is to put the data somewhere other than in the message, and include in the message whatever information is needed for the other process to access it.

Dmitri
  • 9,175
  • 2
  • 27
  • 34
  • Hi dmitri, That's what i will do for now. I will put the data in shared memory to queue less data. Working with files it's always slow compared to shared memory.Thanks for all the help – David S. Nov 21 '11 at 11:47
0

I'd either use a second message queue for the client -> server responses or limit (#sent - #received) to be a safe number.

themel
  • 8,825
  • 2
  • 32
  • 31
  • Thanks for the answer. I have to use one message queue only. To limit the (#sent - #received) i would need to know how much messages of a specific type (producer->worker or worker->producer) exists in the queue and with UNIX MQs i can't know that – David S. Nov 20 '11 at 23:41
  • I don't see why you can not track (tasks sent - results received) in the producer. – themel Nov 21 '11 at 00:39
  • Hi themel, I can track (tasks sent - results received) in the producer but i will follow the dmitri suggestion for now. Thank you for your help :) – David S. Nov 21 '11 at 13:17