Consider the following code. I want to use mutex_by_name() to create and retrieve mutexes. The lock is not a real lock, but should do its job with a one second gap.
Expected output is that m4.lock() fails aka prints lock FAILED because _locked is already set to true. But it does lock. I'm new to C++ and pretty sure I'm missing something obvious. Can you please explain how to implement that correctly.
#include <iostream>
#include <string>
#include <unordered_map>
#include <unistd.h>
class Mutex {
private:
int _id;
bool _locked = false;
void status(std::string s) {
std::cout << _id << " " << name << " " << s << " " << std::endl;
}
public:
const std::string name;
Mutex(std::string name): name(name) {
static int id = 0;
_id = id++;
status("created");
}
Mutex(const Mutex& m): _id(m._id), _locked(m._locked), name(m.name) {
status("copy-constructed");
}
Mutex(Mutex&& m) = delete;
void operator=(Mutex&) = delete;
~Mutex() {
status("deleted");
}
void lock() {
// YES, THIS IS NOT A REAL AND SAFE LOCK
if (!_locked) {
_locked = true;
status("locked");
} else {
status("lock FAILED");
}
}
};
std::unordered_map<std::string, Mutex> mutexe;
Mutex& mutex_by_name(std::string name) {
mutexe.emplace(name, Mutex(name));
auto found = mutexe.find(name);
return found->second;
}
using namespace std;
int main() {
cout << "# 1" << endl;
Mutex m1 = mutex_by_name("hello");
m1.lock();
sleep(1);
cout << "# 2" << endl;
Mutex m4 = mutex_by_name("hello");
m4.lock();
sleep(1);
}
You have to problems. First of all, you're not declaring m1 and m4 as references, and they shall be so.
Secondly, code style :).
So, this shall solve it:
Mutex &m1 = mutex_by_name("hello");
//...
Mutex &m4 = mutex_by_name("hello");
In main you need to make m1 and m4 references (Mutex &m1). Right now they are copies and thus aren't updating the value in the unordered map.
Related
~scoped_lock()
{ std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
How to understand [](auto&... __m) { (__m.unlock(), ...);? I don't understand the ... in lambda and I don't know how this implement release mutexes in reverse order.
Just as #HolyBlackCat say,
(__m.unlock(), ...) means (__m1.unlock(),(__m2.unlock(), (__m3.unlock(), (...)))), but it does not implement unlocking in reverse order.
In cppreference.com :
When control leaves the scope in which the scoped_lock object was created, the scoped_lock is destructed and the mutexes are released, in reverse order.
I make an experiment to confirm this as follows:
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
class mymutex : public std::mutex {
public:
void lock() {
std::mutex::lock();
std::cout << "mutex " << _i << " locked" << std::endl;
}
mymutex(int i): _i(i){}
bool try_lock() {
bool res = std::mutex::try_lock();
if (res) {
std::cout << "mutex " << _i << " try locked" << std::endl;
}
return res;
}
void unlock() {
std::mutex::unlock();
std::cout << "mutex " << _i << " unlocked" << std::endl;
}
private:
int _i;
};
class Speaking {
private:
int a;
mymutex my1;
mymutex my2;
mymutex my3;
public:
Speaking() : a(0), my1(1), my2(2), my3(3){};
~Speaking() = default;
void speak_without_lock();
void speak_with_three_lock();
};
void Speaking::speak_without_lock() {
std::cout << std::this_thread::get_id() << ": " << a << std::endl;
a++;
}
void Speaking::speak_with_three_lock()
{
std::scoped_lock<mymutex, mymutex, mymutex> scoped(my1, my2, my3);
speak_without_lock();
}
int main() {
Speaking s;
s.speak_with_three_lock();
return 0;
}
mutex 1 locked
mutex 2 try locked
mutex 3 try locked
1: 0
mutex 1 unlocked
mutex 2 unlocked
mutex 3 unlocked
So does cppreference make a mistake?
I believe that cppreference.com is incorrect in this detail. C++17 says:
~scoped_lock();
Effects: For all i in [0, sizeof...(MutexTypes)), get(pm).unlock()
which implies that the locks are released in the same order they were taken.
Note that to prevent deadlock, releasing locks in the reverse order of acquiring them is not necessary - it's only necessary to always acquire them in the same order.
#include <iostream>
#include <mutex>
using namespace std;
class TestClass {
public : // members
std::mutex m_mutex;
int m_var;
public : //functions
TestClass()
:m_var(0) {};
void fooIncVar()
{
cout << "calling inc var" << endl;
std::scoped_lock lock(m_mutex);
_incVar();
}
private:
void _incVar()
{
std::scoped_lock lock(m_mutex);
m_var++;
cout << "var : " << m_var << endl;
}
};
int main()
{
cout<<"Hello World" << endl;
auto a = A();
a.fooIncVar();
return 0;
}
I am trying to understand how scoped_lock works with a mutex. I was expecting that below program will just hang because I am calling _incVar by holding the mutex in fooIncVar since scope of the variable is until the end of the function. But that doesn't seem to be the case. I get the following output
Hello World
calling inc var
var : 1
I have a class object obj1 and I am trying to call a member function sdf_write from 2-separate-threads.
There is a static variable wr_count inside the member-function.
The issue is: when I run both threads, the wr_count value is being shared between both threads.
For e.g. thread_1 runs 8-times and makes the wr_count=8 but when thread_2 starts it makes the wr_count=9. I want thread_2 to start counting from "1" not from the last value of thread_1.
Here is my code:
#include <iostream>
#include <stdio.h>
#include <thread>
#include "sdf_func.hpp"
#include <vector>
using namespace std;
int main() {
sdf obj1;
std::thread t1([&obj1](){
for (int i=0; i<30; i++) {
while (!obj1.sdf_write(10));
};
});
t1.detach();
std::thread t2([&obj1](){
for (int i=0; i<30; i++) {
while (!obj1.sdf_write(10));
};
});
t2.join();
cout << "done: " << obj1.done << endl;
// cout << "done: " << obj2.done << endl;
// cout << "wr_count: " << obj1.wr_count << endl;
return 0;
}
// This is sdf_func/////////////////
#include <iostream>
#include <stdio.h>
#include <thread>
#include <mutex>
using namespace std;
class sdf {
public:
int done;
std::mutex mutex;
sdf() : done(0){};
void increment() {
std::lock_guard<std::mutex> guard(mutex);
++done;
}
bool sdf_write (auto size) {
static int wr_count = 0;
if (wr_count == size) {
wr_count = 0;
increment();
//cout << "done : " << done;
return false;
}
wr_count++;
cout << wr_count << "--" << std::this_thread::get_id() << endl;
return true;
}
};
This is a perfect job for the thread_local storage duration, which is a keyword introduced from C++11.
thread_local int wr_count;
Essentially, you get a separate static instance of wr_count per thread; each one is initialised to 0.
Reference: http://en.cppreference.com/w/cpp/keyword/thread_local
I would like to have a C++11 RAII component to count how many resources of a certain type are present in a multithreaded environment. I wrote the following:
#include <atomic>
#include <iostream>
using namespace std;
class AtomicCounter
{
public:
AtomicCounter(std::atomic< int > &atomic) : atomic(atomic) {
int value = ++this->atomic;
cerr << "incremented to " << value << endl;
}
~AtomicCounter() {
int value = --this->atomic;
cerr << "decremented to " << value << endl;
}
private:
std::atomic< int > &atomic;
};
int main() {
atomic< int > var;
var = 0;
AtomicCounter a1(var);
{
AtomicCounter a2(var);
cerr << "Hello!" << endl;
AtomicCounter a3(var);
}
cerr << "Good bye!" << endl;
return 0;
}
The idea is that I create an AtomicCounter object in each resource (for example, the main thread function) and this keeps the associated atomic variable updated.
Is this component correct, even when used in a multithreaded environment? Is there a standard component that already does this?
I have a simple piece of code (Checker) which carries out some consistency checks on the elements of a vector (pps)
try{
const Checker& results = std::for_each(pps.begin(), pps.end(), Checker());
!results.diagnostic();
}
catch(std::bad_alloc&){
cout << "the check operation failed: out of memory" << endl;
}
Checker has a member function (diagnostic) which outputs the results of this check.
The problem is: if for some reason (std::bad_alloc, for example) the check operation gets interrupted, i would like to have the already produced diagnostic available. Is it possible without recurring to a "substantial rewrite" allowing me to do something like:
Checker::Diagnostic diagnostic;
try{
std::for_each(pps.begin(), pps.end(), Checker(diagnostic));
}
catch(std::bad_alloc&){
cout << "the check operation failed: out of memory" << endl;
}
diagnostic.output();
This would look unnatural, since the return of std::for_each is intended for the exact purpose of being able to do such things, and the exceptional flow of control would dominate the look of the code.
I would prefer to use the class like this:
Checker checker;
checker.doCheck(pps);
checker.diagnostic();
Or:
const Checker checker(pps);
checker.diagnostic();
That way, you can hide the details of the check in doCheck() (first example) or in the constructor (second example).
For example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
using ImportantItems = std::vector<int>;
class Checker {
public:
Checker(const int criticalItem) : criticalItem(criticalItem) { }
void doCheck(const ImportantItems& items)
{
accumulatedSum = 0;
try {
std::for_each(
items.begin(), items.end(),
boost::bind(&Checker::performExtensiveCheckingOnAnItem, this, _1));
this->dataOk = true;
}
catch (const std::runtime_error& e) {
this->dataOk = false;
}
std::cout << "AddAccumulated sum: " << accumulatedSum << std::endl;
}
void diagnostic() const
{
if (this->dataOk) {
std::cout << "Everything was fine in last check" << std::endl;
}
else {
std::cout << "Serious problems encountered" << std::endl;
}
}
private:
void performExtensiveCheckingOnAnItem(const int anItem)
{
if (criticalItem == anItem) {
throw std::runtime_error("Critical situation");
}
accumulatedSum += anItem;
}
const int criticalItem;
int accumulatedSum{};
bool dataOk{false};
};
int main()
{
const int criticalItem(5);
const ImportantItems importantItems{1, 2, 3, 4/*, criticalItem*/};
Checker checker(criticalItem);
checker.doCheck(importantItems);
checker.diagnostic();
return 0;
}