Boost logo

Boost :

Subject: Re: [boost] [Interprocess::Semaphore] Deadlock on more producers - one consumer problem
From: Cosimo Calabrese (cosimo.calabrese_at_[hidden])
Date: 2009-06-20 11:11:04


http>
> Forget this response. We have system V semaphores with this feature.
> Interprocess models POSIX interface and that's why post is V(1).
>

Ion, James

thanks to all for the answers. Sorry for the delay in my reply. And
sorry for the uppercase in this reply, I've used it only for a better
explanation. And sorry for the too long post...

Yes, it's true, I've said: "the post() unlocks only one of the 4
producers", but perhaps I've badly explained the problem.
I don't want to wake up all waiters with a single post(), but only one
waiter every time I post() the semaphore, independently from the counter
value. The problem is that the interprocess::semaphore() doesn't wake up
a waiter EVERY TIME I post() the semaphore, but only if the counter is 0.
If the buffer has more of one free resource, and I've more of one waiter
locked, EVERY TME I post() the semaphore should unlock ONE of the waiters.

I'm working under Windows XP, so I've analized the "emulation"
implementation of the semaphore interface (the posix implementation is a
simple wrapper of the POSIX semaphore). The emulation module implements
the post() like this:

inline void interprocess_semaphore::post()
{
    scoped_lock<interprocess_mutex> lock(m_mut);
    if(m_count == 0){
       m_cond.notify_one();
    }
    ++m_count;
}

- From the cited http://en.wikipedia.org/wiki/Semaphore_(programming),
it isn't mentioned the requirement to check if the semaphore counter is
0 for release a waiter.

- Ion, you've said: "V can only wake a single thread, because the
semaphore count represents the free resource count". I am perfectly
agree with you. But this should be done independently from the counter
value, not only when the counter is 0.

- Ion, you've also said: "Interprocess models POSIX interface and that's
why post is V(1)". I'm agree with you if you do V(1), but not if you do:

if ( sempaphore_counter == 0 ) {
    V(1);
}

- I've modeled my consumers - producer problem like described in the
cited
http://en.wikipedia.org/wiki/Producer-consumer_problem#Using_semaphores

procedure consumer() {
     while (true) {
         down(fillCount)
         item = removeItemFromBuffer()
         up(emptyCount)
         consumeItem(item)
     }
}

But using the interprocess::semaphore, the up() operation correctly
unlocks one of the locked threads, but ONLY if counter == 0.

- From boost documentation:
http://www.boost.org/doc/libs/1_39_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores:
"Post: Increments the semaphore count. If any process is blocked, one of
those processes is awoken."
So, not only when the semaphore counter is 0.

- From boost documentation too:
http://www.boost.org/doc/libs/1_39_0/doc/html/boost/interprocess/interprocess_semaphore.html#id1772618-bb
void post() ;
Increments the interprocess_semaphore count. If there are
processes/threads blocked waiting for the interprocess_semaphore, then
one of these processes will return successfully from its wait function.
[...]

This is exactly the Dijkstra semaphore behaviour; but for correctly
describe the interprocess::semaphore lacks the words: "...only if the
counter is 0"

I hope to have explained my point of view.

Best,
Cosimo Calabrese.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk