Suppose I have two threads and one shared c++ 11 condition variable. What whould happen if thread1 call notify and after that thread2 call wait? Will thread2 block forever or it will continue it's work due to call of notify by thread1?
Edit:
enum bcLockOperation
{
bcLockOperation_Light = -1,
bcLockOperation_Medium = 50,
bcLockOperation_Heavy = 1
}
class BC_COREDLL_EXP bcCustomMutex
{
private:
bcCustomMutex(const bcCustomMutex&);
bcCustomMutex& operator=(const bcCustomMutex&);
protected:
bcAtomic<int> mFlag;
bcMutex mMutex;
bcConditionVariable mCond;
public:
bcCustomMutex() { bcAtomicOperation::bcAtomicInit(mFlag, 0); };
~bcCustomMutex() {};
void lock(bcLockOperation pLockOperation = bcLockOperation_Medium)
{
bcINT32 lNewLoopCount = static_cast<bcINT32>(pLockOperation);
bcINT32 lLoopCounter = 0;
bcINT32 lExpected = 0;
bcINT32 lLoopCount = bcAtomicOperation::bcAtomicLoad(mFlag, bcMemoryOrder_Relaxed);
while (true)
{
while(bcAtomicOperation::bcAtomicLoad(mFlag, bcMemoryOrder_Relaxed) != 0 && lLoopCounter != lLoopCount)
++lLoopCounter;
bcAtomicOperation::bcAtomicCompareExchangeStrong(
mFlag,
&lExpected,
lNewLoopCount,
bcMemoryOrder_Acquire,
bcMemoryOrder_Relaxed);
if(lExpected == 0)
{
return;
}
else if(lLoopCounter == lLoopCount)
{
bcLockGuard<bcMutex> lGuard(mMutex);
mCond.wait(mMutex);
}
else
{
continue;
}
}
void UnLock()
{
bcAtomicOperation::bcAtomicStore(mFlag, 0, bcMemoryOrder_Relaxed);
bcUniqueLock<bcMutex> lGuard(mMutex);
mCond.notifyOne();
}
bcBOOL TryLock()
{
};
};
I want to write a custom mutex such that each thread can provide an argument that represents the complexity of operations that the current thread wants to execute. If the complexity of the operation is low other threads will be in a loop like a spin lock but if the complexity of the operation is medium each thread will iterate 50 times and then will sleep by condition variable and if operation is very complex other threads will go to sleep directly.
now assume thread1 locks this mutex and thread2 goes for waiting due to its loopCounter reaching its end and right before locking the condition variable's mutex, thread1 calls notify on the condition variable. Now thread2 will sleep until another thread locks the custom mutex and then calls unlock on it.
I am new to multithreading and I want to learn. I know that my class may contain errors or may be completely wrong, but is there any way to correct this problem or a good algorithm to write such a mutex.
The reason of necessity of using while loop is there are only two functions in the std::condition_variable for awakening waiting threads: notify_one() which awakes one of the threads currently waiting for this condition without possibility to point which one to awake exactly.
The condition_variable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until another thread both modifies a shared variable (the condition), and notifies the condition_variable .
Condition variables are used to wait until a particular condition predicate becomes true. This condition predicate is set by another thread, usually the one that signals the condition. A condition predicate must be protected by a mutex.
A condition variable is created by calling the pthread_cond_init subroutine. You may specify a condition attributes object. If you specify a NULL pointer, the condition variable will have the default attributes.
Thread2 will block until someone calls notify. Calls to notify release threads that are waiting at the time of the call. If there are no threads waiting, they do nothing. They aren't saved.
Usually both the code that decides to wait and the code that decides to notify share the same mutex. So thread2 will never "miss" the notify from thread1.
Here's the classic lock-based concurrent queue example:
void push(int x)
{
lock_guard<mutex> guard{queue_mutex};
thequeue.push(x);
not_empty_condition.notify_one();
}
int pop()
{
unique_lock<mutex> guard{queue_mutex};
not_empty_condition.wait(guard, []{ return !thequeue.empty(); } );
int x = thequeue.front();
thequeue.pop();
return x;
}
Assume thread1 and thread2 are running push()
and pop()
respectively. Only one of them will be in the critical section at a time.
If thread2 has the lock, either it never waits because the queue is not empty (so "losing" a notify is harmless), or it sits there waiting for a notify (which won't be lost).
If thread1 got the lock, it will put an element in the queue; if thread2 was waiting, it will get notified properly; if thread2 was still waiting for the mutex, it will never wait, as there is at least one element on the queue, so losing a notify is harmless.
In this manner, a notify is only lost if it was not needed in the first place.
Now, if you have a different usage for condition variables in mind, where "losing" a notification has any consequence, I believe you either have a race condition, or are using the wrong tool altogether.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With