Implementing a Semaphore with std::mutex - c++

As a learning exercise, I'm just trying to make a Semaphore class using std::mutex and a few other things provided by the C++ standard. My semaphore should allow as many readLock() as needed, however a writeLock() can only be acquired after all reads are unlocked.
//Semaphore.h
#include <mutex>
#include <condition_variable>
class Semaphore{
public:
Semaphore();
void readLock(); //increments the internal counter
void readUnlock(); //decrements the internal counter
void writeLock(); //obtains sole ownership. must wait for count==0 first
void writeUnlock(); //releases sole ownership.
int count; //public for debugging
private:
std::mutex latch;
std::unique_lock<std::mutex> lk;
std::condition_variable cv;
};
//Semaphore.cpp
#include "Semaphore.h"
#include <condition_variable>
#include <iostream>
using namespace std;
Semaphore::Semaphore() : lk(latch,std::defer_lock) { count=0; }
void Semaphore::readLock(){
latch.lock();
++count;
latch.unlock();
cv.notify_all(); //not sure if this needs to be here?
}
void Semaphore::readUnlock(){
latch.lock();
--count;
latch.unlock();
cv.notify_all(); //not sure if this needs to be here?
}
void Semaphore::writeLock(){
cv.wait(lk,[this](){ return count==0; }); //why can't std::mutex be used here?
}
void Semaphore::writeUnlock(){
lk.unlock();
cv.notify_all();
}
My test program will writeLock() the semaphore, start a bunch of threads, and then release the semaphore. Immediately afterwards, the main thread will attempt to writeLock() the semaphore again. The idea is that when the semaphore becomes unlocked, the threads will readLock() it and prevent the main thread from doing anything until they all finish. When they all finish and release the semaphore, then the main thread can acquire access again. I realize this may not necessarily happen, but it's one of the cases I'm looking for.
//Main.cpp
#include <iostream>
#include <thread>
#include "Semaphore.h"
using namespace std;
Semaphore s;
void foo(int n){
cout << "Thread Start" << endl;
s.readLock();
this_thread::sleep_for(chrono::seconds(n));
cout << "Thread End" << endl;
s.readUnlock();
}
int main(){
std::srand(458279);
cout << "App Launch" << endl;
thread a(foo,rand()%10),b(foo,rand()%10),c(foo,rand()%10),d(foo,rand()%10);
s.writeLock();
cout << "Main has it" << endl;
a.detach();
b.detach();
c.detach();
d.detach();
this_thread::sleep_for(chrono::seconds(2));
cout << "Main released it" << endl;
s.writeUnlock();
s.writeLock();
cout << "Main has it " << s.count << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "Main released it" << endl;
s.writeUnlock();
cout << "App End" << endl;
system("pause"); //windows, sorry
return 0;
}
The program throws an exception saying "unlock of unowned mutex". I think the error is in writeLock() or writeUnlock(), but I'm not sure. Can anyone point me in the right direction?
EDIT: There was a std::defer_lock missing when initializing lk in the constructor, however it didn't fix the error I was getting. As mentioned in the comment, this isn't a semaphore and I apologize for the confusion. To reiterate the problem, here is the output that I get (things in parenthesis are just my comments and not actually in the output):
App Launch
Thread Start
Thread Start
Main has it
Thread Start
Thread Start
Thread End (what?)
Main released it
f:\dd\vctools\crt_bld\self_x86\crt\src\thr\mutex.c(131): unlock of unowned mutex
Thread End
Thread End
Thread End

This is definitely not a "semaphore".
Your Semaphore constructor acquires the lock on latch right away, then you unlock it twice because writeUnlock() calls lk.unlock() and the next call to writeLock() tries to wait on a condition variable with an unlocked mutex, which is undefined behaviour, then you the next call to writeUnlock() tries to unlock an unlocked mutex, which is also undefined behaviour.
Are you sure the constructor should lock the mutex right away? I think you want to use std::defer_lock in the constructor, and then lock the mutex in writeLock().

Related

How to identify which thread is holding a mutex

Is it possible to identify which thread is holding the mutex? I'm facing an issue in which one of my thread has indefinitely got blocked in acquiring a mutex. I'm using std::lock_guard<std::mutex> lg(mut) syntax to acquire a lock which basically follows RAII pattern.
You can get the current thread id via get_id:
#include <thread>
#include <mutex>
#include <iostream>
void foo() {
{
static std::mutex mut;
std::lock_guard<std::mutex> lg(mut);
std::cout << "thread holding the lock: " << std::this_thread::get_id() << "\n";
std::cout << "Hello \n";
}
std::cout << "thread " << std::this_thread::get_id() << " no longer holds the lock \n";
}
int main() {
std::thread t1(&foo);
std::thread t2(&foo);
t1.join();
t2.join();
}
Output:
thread holding the lock: 140607394023168
Hello
thread 140607394023168 no longer holds the lock
thread holding the lock: 140607385630464
Hello
thread 140607385630464 no longer holds the lock
My next idea would be to wrap the std::mutex into a my_mutex which remembers which thread currently holds the lock. Though, that would require to use another mutex to synchronize access to that information, hence logging seems to be the better way.

Does std::lock_guard release the mutex after constructed with std::adopt_lock option?

I know my question is quite similar to this Why does std::lock_guard release the lock after using std::adopt_lock?, but the behavior I see is not. Here is my code:
#include <mutex>
#include <iostream>
using namespace std;
std::mutex m;
void fun2();
void fun1() {
cout << "fun1" << endl;
std::unique_lock<std::mutex> guard(m);
cout << "lock mutex" << endl;
fun2();
if (guard.owns_lock()) {
cout << "still holds mutex" << endl;
}
else {
cout << "doesn't hold mutex" << endl;
}
}
void fun2() {
std::lock_guard<std::mutex> guard(m, std::adopt_lock);
cout << "fun2" << endl;
}
int main(int argc, char* argv[]) {
fun1();
return 0;
}
And this is the result I get:
fun1
lock mutex
fun2
still holds mutex
Clearly, the unique_lock in fun1 still holds the mutex. So my question is "Does std::lock_guard release the mutex after constructed with std::adopt_lock option?". Hope you all can help me clarify this situation. Thank you.
When you constructed a std::unique_lock to manage the mutex, you should stick to it unless you first break the association of the std::unique_lock with the mutex using std::unique_lock::release. In your sample, you touched the raw mutex when it's still managed by a std::unique_lock and this is wrong.
The program has undefined behavior.
You've created two guards that both think they own the mutex and they will both unlock it. That's UB.
Using m.lock() in fun1 instead of using a guard would be one way to make it have defined behavior.

c++ std::thread: Is this code guaranteed to deadlock?

The following code is from modernescpp. I understand that when the lock_guard in the main thread holding the mutex causes the deadlock. But since the created thread should start to run once it is initialized. Is there a chance that after line 15 the functions lock_guard on line 11 already grabbed coutMutex so the code runs without any problem? If it is possible, under what circumstance the created thread
will run first?
#include <iostream>
#include <mutex>
#include <thread>
std::mutex coutMutex;
int main(){
std::thread t([]{
std::cout << "Still waiting ..." << std::endl;
std::lock_guard<std::mutex> lockGuard(coutMutex); // Line 11
std::cout << std::this_thread::get_id() << std::endl;
}
);
// Line 15
{
std::lock_guard<std::mutex> lockGuard(coutMutex);
std::cout << std::this_thread::get_id() << std::endl;
t.join();
}
}
Just so the answer will be posted as an answer, not a comment:
No, this code is not guaranteed to deadlock.
Yes, this code is quite likely to deadlock.
In particular, it's possible for the main thread to create the subordinate thread, and then both get suspended. From that point, it's up to the OS scheduler to decide which to run next. Since the main thread was run more recently, there's a decent chance it will select the subordinate thread to run next (assuming it attempts to follow something vaguely like round-robin scheduling in the absence of a difference in priority, or something similar giving it a preference for which thread to schedule).
There are various ways to fix the possibility of deadlock. One obvious possibility would be to move the join to just outside the scope in which the main thread holds the mutex:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex coutMutex;
int main(){
std::thread t([]{
std::cout << "Still waiting ..." << std::endl;
std::lock_guard<std::mutex> lockGuard(coutMutex); // Line 11
std::cout << std::this_thread::get_id() << std::endl;
}
);
// Line 15
{
std::lock_guard<std::mutex> lockGuard(coutMutex);
std::cout << std::this_thread::get_id() << std::endl;
}
t.join();
}
I'd also avoid locking a mutex for the duration of using std::cout. cout is typically slow enough that doing so will make contention over the lock quite likely. It's typically doing to be better to (for only one example) format the data into a buffer, put the buffer into a queue, and have a single thread that reads items from the queue and shoves them out to cout. This way you only have to lock for long enough to add/remove a buffer to/from the queue.

What's the proper way of implementing 'sleeping' technique using C++?

Two thread. Main one is constantly gathering notifications while the other one is processing some of them.
The way i implemet it - is not correct as i've been told. What problems is it causing and what's wrong about it?
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>
std::condition_variable foo;
std::mutex mtx;
void secondThread()
{
while (true)
{
foo.wait(std::unique_lock<std::mutex>(mtx));
std::cout << " ----------------------------" << std::endl;
std::cout << "|processing a notification...|" << std::endl;
std::cout << " ----------------------------" << std::endl;
}
}
int main()
{
std::thread subThread = std::thread(&secondThread);
int count = 0;
while (true)
{
if (count % 10 == 0)
{
foo.notify_one();
}
std::cout << "Main thread working on gathering notifications..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
count++;
}
return 0;
}
I was told that this foo.wait(std::unique_lock<std::mutex>(mtx)) line of code is not a good practice according to the C++ spec. This is not a proper way of solving this kind of problem. It's also called, sleeping(not busy waiting).
Before you call wait, you must check that the thing you are waiting for hasn't already happened. And before you stop calling wait, you must check that the thing you are waiting for has happened. Condition variables are stateless and have no idea what you're waiting for. It's your job to code that.
Also, the associated mutex must protect the thing you're waiting for. The entire point of a condition variable is to provide an atomic "unlock and wait" operation to prevent this problem:
You check if you need to wait under the protection of a mutex.
You decide you do need to wait.
You unlock the mutex so other threads can make progress.
You wait.
But what if the thing you're waiting for happens after you unlocked the mutex but before you waited? You'll be waiting for something that already happened.
This is why the wait function takes a lock holder -- so that it can perform steps 3 and 4 atomically.

unique_lock across threads?

I am having some trouble conceptualizing how unique_lock is supposed to operate across threads. I tried to make a quick example to recreate something that I would normally use a condition_variable for.
#include <mutex>
#include <thread>
using namespace std;
mutex m;
unique_lock<mutex>* mLock;
void funcA()
{
//thread 2
mLock->lock();//blocks until unlock?Access violation reading location 0x0000000000000000.
}
int _tmain(int argc, _TCHAR* argv[])
{
//thread 1
mLock = new unique_lock<mutex>(m);
mLock->release();//Allows .lock() to be taken by a different thread?
auto a = std::thread(funcA);
std::chrono::milliseconds dura(1000);//make sure thread is running
std::this_thread::sleep_for(dura);
mLock->unlock();//Unlocks thread 2's lock?
a.join();
return 0;
}
unique_lock should not be accessed from multiple threads at once. It was not designed to be thread-safe in that manner. Instead, multiple unique_locks (local variables) reference the same global mutex. Only the mutex itself is designed to be accessed by multiple threads at once. And even then, my statement excludes ~mutex().
For example, one knows that mutex::lock() can be accessed by multiple threads because its specification includes the following:
Synchronization: Prior unlock() operations on the same object shall synchronize with (4.7) this operation.
where synchronize with is a term of art defined in 4.7 [intro.multithread] (and its subclauses).
That doesn't look at all right. First, release is "disassociates the mutex without unlocking it", which is highly unlikely that it is what you want to do in that place. It basically means that you no longer have a mutex in your unique_lock<mutex> - which will make it pretty useless - and probably the reason you get "access violation".
Edit: After some "massaging" of your code, and convincing g++ 4.6.3 to do what I wanted (hence the #define _GLIBCXX_USE_NANOSLEEP), here's a working example:
#define _GLIBCXX_USE_NANOSLEEP
#include <chrono>
#include <mutex>
#include <thread>
#include <iostream>
using namespace std;
mutex m;
void funcA()
{
cout << "FuncA Before lock" << endl;
unique_lock<mutex> mLock(m);
//thread 2
cout << "FuncA After lock" << endl;
std::chrono::milliseconds dura(500);//make sure thread is running
std::this_thread::sleep_for(dura); //this_thread::sleep_for(dura);
cout << "FuncA After sleep" << endl;
}
int main(int argc, char* argv[])
{
cout << "Main before lock" << endl;
unique_lock<mutex> mLock(m);
auto a = std::thread(funcA);
std::chrono::milliseconds dura(1000);//make sure thread is running
std::this_thread::sleep_for(dura); //this_thread::sleep_for(dura);
mLock.unlock();//Unlocks thread 2's lock?
cout << "Main After unlock" << endl;
a.join();
cout << "Main after a.join" << endl;
return 0;
}
Not sure why you need to use new to create the lock tho'. Surely unique_lock<mutex> mlock(m); should do the trick (and corresponding changes of mLock-> into mLock. of course).
A lock is just an automatic guard that operates a mutex in a safe and sane fashion.
What you really want is this code:
std::mutex m;
void f()
{
std::lock_guard<std::mutex> lock(m);
// ...
}
This effectively "synchronizes" calls to f, since every thread that enters it blocks until it manages to obtain the mutex.
A unique_lock is just a beefed-up version of the lock_guard: It can be constructed unlocked, moved around (thanks, #MikeVine) and it is itself a "lockable object", like the mutex itself, and so it can be used for example in the variadic std::lock(...) to lock multiple things at once in a deadlock-free way, and it can be managed by an std::condition_variable (thanks, #syam).
But unless you have a good reason to use a unique_lock, prefer to use a lock_guard. And once you need to upgrade to a unique_lock, you'll know why.
As a side-note, the above answers skip over the difference between immediate and deferred locking of mutex:
#include<mutex>
::std::mutex(mu);
auto MyFunction()->void
{
std::unique_lock<mutex> lock(mu); //Created instance and immediately locked the mutex
//Do stuff....
}
auto MyOtherFunction()->void
{
std::unique_lock<mutex> lock(mu,std::defer_lock); //Create but not locked the mutex
lock.lock(); //Lock mutex
//Do stuff....
lock.unlock(); //Unlock mutex
}
MyFunction() shows the widely used immediate lock, whilst MyOtherFunction() shows the deferred lock.