Results 1 to 4 of 4

Thread: 1 producer 14 Consumers problem

  1. #1
    Join Date
    Jan 2008
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default 1 producer 14 Consumers problem

    Hi everyone.

    We are trying to develop an application involving 1 producer and 14 consumers simultaneously accessing a circular buffers.

    The producer is entitled to produce data bytes and store them into several buffers (depending on the kind of data it produces). The consumers are entitled to retrieve data bytes from the buffer and use them to perform operations such as graphic display and file data logging.

    Basically there are the producer and a pair of consumers per circular buffer; one consumer for graphic display and another one for file data logging. There is a total of 7 buffers each of which refers to a specific physical data acquisition channel.

    The concurrent access to the circular buffer is protected by a pair of semaphores, and one mutex (that we believe can be removed).

    The application run smoothly for a limited number of channels but it crashes when handling all the 7 channels.

    Running in debug mode QT4.5 under Windows XP - SP3, we observe that the application get stuck during the call to tryAcquire, and more specifically to the QMutexLocker locker(&d->mutex); statement of it.

    Do you think that there is a maximum amount of semaphores that can be used within an application ?
    Do you have any suggestion on things that need to be considered while dealing with threads, semaphores, mutexes and such ?

    Thanks to you all.
    Attached Files Attached Files

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: 1 producer 14 Consumers problem

    I'm sorry to say that but your code doesn't make much sense... To handle a circular buffer, regardless of the number of consumers you only need one semaphore and optionally one mutex (but you can avoid having it for example by using QAtomicPointer).

    Here is a rough implementation of a circular buffer (let's assume it holds integers, for simplicity):
    Qt Code:
    1. class CircularBuffer {
    2. public:
    3. CircularBuffer(int size), m_sem(0) {
    4. m_data = new int(size);
    5. m_firstToRead = 0;
    6. m_firstToWrite = 0;
    7. m_size = size;
    8. }
    9. int read() {
    10. m_sem.acquire(1);
    11. m_mutex.lock(); // protect m_firstToRead
    12. int val = m_data[m_firstToRead];
    13. m_firstToRead = (m_firstToRead+1) % m_size;
    14. m_mutex.unlock();
    15. return val;
    16. }
    17. void write(int val) {
    18. m_data[m_firstToWrite] = val;
    19. m_firstToWrite = (m_firstToWrite+1) % m_size;
    20. m_sem.release(1);
    21. }
    22. private:
    23. QSemaphore m_sem;
    24. int m_firstToRead;
    25. int m_firstToWrite;
    26. int m_size;
    27. QMutex m_mutex;
    28. };
    To copy to clipboard, switch view to plain text mode 

    If you want more than one producer, you need to protect m_firstToWrite as well.

    If you need more buffers, or a buffer of buffers, just repeat the pattern. Allocating an array of arrays of semaphores is probably a very bad idea.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Jan 2008
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: 1 producer 14 Consumers problem

    Hi there. Thank yopu very much for you helpful comment. I appreciated it very much, especially the part where you say that what I write does not make sense.

    But let's move forward and let's take the discussion on technical issues rather than personal judgments.

    The idea underlying my class is to have a circular buffer able to serve one producer and several consumers. All the consumers must be able to read each byte produced by the producer, and the producer must wait until all the consumers have retrieved the produced data. I do not see anything like that in your implementation.

    Furthermore, there are no arrays of arrays of semaphores. There is one array of pointers to semaphores. Each semaphore is related to a different consumer, and since all the consumers live a separate life, there must be an independent semaphore for each one of them.

    Thank you anyway.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: 1 producer 14 Consumers problem

    Quote Originally Posted by tsyahoo View Post
    The idea underlying my class is to have a circular buffer able to serve one producer and several consumers. All the consumers must be able to read each byte produced by the producer, and the producer must wait until all the consumers have retrieved the produced data. I do not see anything like that in your implementation.
    You forgot to mention that in your post

    What you want is broadcast, not a synchronized access to data (and you can do it with events). And you don't need semaphores for that. If you want to keep it the way it is, there is QAtomicInt that can be incremented atomically which is sufficient for your task.

    Still you need a single semaphore to protect the buffer itself but then you only need to make sure all consumers accessed the data before overwriting it. You can do it in one of two ways:

    1. each item in the buffer has its own semaphore that gets released (with the value of 1) by each consumer after reading the data and gets acquired (with the value of 14 or whatever the amount of consumers you have per cell) by the producer. This makes sure the producer overwrites data in a cell only if all consumers have already accessed it.

    2. each item in the buffer has a counter that gets incremented when a consumer accessed it. The producer has to wait until the value of that counter equals the number of consumers (+1 if the producer itself also increments the buffer to provide consistency). This can also be implemented using a mutex and a wait condition to make sure the producer only reads the counter if its value has changed recently.

    Right now I can think of at least one more way involving two semaphores and a bunch of QAtomicInt objects to solve the task. One semaphore protects the buffer from overrunning, the other from underrunning. One is released by the producer each time it writes an item, the other is released by the last consumer accessing the item. Consumers use the atomic integer to check if they are the last one to read the data and if they should release the semaphore.

    Here is the supposed code for implementing the consumer:

    Qt Code:
    1. int currentIndex = ...;
    2.  
    3. underrunSemaphore.acquire(1);
    4. consumeData(data[currentIndex]);
    5. int val = data[currentIndex].counter.fetchAndAddOrdered(1);
    6. if(val==1){
    7. // I'm the second (last) consumer to access the data
    8. overrunSemaphore.release(1);
    9. }
    10. currentIndex++;
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 16
    Last Post: 28th October 2008, 22:00
  2. Weird problem: multithread QT app kills my linux
    By Ishark in forum Qt Programming
    Replies: 2
    Last Post: 8th August 2008, 09:12
  3. Steps in solving a programming problem?
    By triperzonak in forum General Programming
    Replies: 8
    Last Post: 5th August 2008, 08:47
  4. QSemaphore: 1 Producer, 3 Consumers
    By Daedalus in forum Newbie
    Replies: 9
    Last Post: 1st April 2007, 20:59
  5. Replies: 16
    Last Post: 7th March 2006, 15:57

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.