Reputation: 1750
I'm trying to implement a multi-in multi-out interthread channel class. I have three mutexes: full
locks when buffer is full. empty
locks when buffer is empty. th
locks when anyone else is modifying buffer. My single IO program looks like
operator<<(...){
full.lock() // locks when trying to push to full buffer
full.unlock() // either it's locked or not, unlock it
th.lock()
...
empty.unlock() // it won't be empty
if(...)full.lock() // it might be full
th.unlock()
operator>>(...){
// symmetric
}
This works totally fine for single IO. But for multiple IO, when consumer thread unlocks full
, all provider thread will go down, only one will obtain th
and buffer might be full again because of that single thread, while there's no full check anymore. I can add a full.lock()
again of course, but this is endless. Is there anyway to lock full
and th
at same time? I do see a similar question about this, but I don't see order is the problem here.
Upvotes: 3
Views: 6364
Reputation: 44288
Functonality you try to achieve would require something similar to System V semaphores, where group of operations on semaphors could be applied atomically. In your case you would have 3 semaphores:
then push operation would do this group to lock:
then
to unlock. then to pull data first group would be changed to:
unlock is the same as before. Using mutexes, which are special case semaphores most probably would not solve your problem this way. First of all they are binary ie only have 2 states but more important API does not provide group operations on them. So you either find semaphore implementation for your platform or use single mutex with condition variable(s) to signal waiting threads that data or buffer is available.
Upvotes: -1
Reputation: 1519
No, you can't atomically lock two mutexes.
Additionally, it looks like you are locking a mutex in one thread and then unlocking it in another. That's not allowed.
I suggest switching to condition variables for this problem. Note that it's perfectly fine to have one mutex associated with multiple condition variables.
Upvotes: 2
Reputation: 3305
Yes, use std::lock(full , th);
, this could avoid some deadlocks
for example: thread1:
full.lock();
th.lock();
thread2:
th.lock();
full.lock();
this could cause a deadlock, but the following don't:
thread1:
std::lock(full, th);
thread2:
std::lock(th, full);
Upvotes: 7