#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
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.
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 have a question regarding the outside modification of a running method.
Given this C++ class:
#include <iostream>
class Foo {
public:
Foo()
: runBar(true) {}
void bar() {
int i = 0;
while(this->runBar) {
std::cout << "Loop " << i++ << std::endl;
}
std::cout << "Loop done!" << std::endl;
}
void baz() {
this->runBar = false;
std::cout << "Field changed!" << std::endl;
}
private:
bool runBar;
};
And also given this main function:
int main(int argc, char* argv[]) {
Foo f;
f.bar();
f.baz();
return 0;
}
What happens when the call to Foo::baz() is made?
Thanks for the help!
Since you only have 1 thread of execution, and you do not have anything to change the while loop exit condition in the bar function, this code will loop forever. Your baz function will never be called.
Assuming you meant to call them from separate threads,
here is an example showing main modified to call the function from within a thread.
Foo is using a mutext to coordinate activity, like allowing the thread to finish printing before being terminated.
The join prevents termination of main from ending everything prematurely.
If you don't coordinate them in some way such as that, it would not possible to say with certainty what the sequence of events would be. Such is the nature of programming with multiple threads.
Either bar runs first in which case it prints, or else baz runs first in which case bar will not. Either is possible.
#include <iostream>
#include <mutex>
mutex aMutex; //<--
class Foo {
public:
Foo()
: runBar(true) {}
void bar() {
int i = 0;
while(this->runBar) {
aMutex.lock(); //<--
std::cout << "Loop " << i++ << std::endl;
aMutex.unlock(); //<--
}
std::cout << "Loop done!" << std::endl;
}
void baz() {
this->runBar = false;
aMutex.lock(); //<--
std::cout << "Field changed!" << std::endl;
aMutex.unlock(); //<--
}
private:
bool runBar;
};
#include <thread>
int main(int argc, char* argv[]) {
Foo f;
thread myThread { f.bar() }; //call it in a thread
f.baz();
myThread.join(); //<--
return 0;
}
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.
I am using a pattern like this, C++11:
class FooViewController {
void build() {
auto label = ...
network->doWork([] (const Result& r) {
label->setText(r.text);
});
}
}
FooViewController may deconstruct before doWork completes, causing crashes. Looking at boost::signals2, I'm thinking of using boost::signals2::trackable, which works great for my single threaded purposes, with the benefit that I do not have to hold and manage my connections directly, however I'm not sure how to get such a solution working with lambdas.
Here is a working lambda free version:
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!");
}
};
Usage:
boost::signals2::signal<void()> signal;
{
Foo test;
signal.connect(boost::bind(&Foo::bar, &test));
signal();
}
signal();
Output:
Fired!
// Note a second 'Fired!' did not occur, which is correct behavior
Two goals:
1-- I'd like to do something like:
signal.connect(boost::bind([] {
printf("Fired!");
}, &test));
Which would NOT call the lambda after test is torn down.
2-- I do not want to directly manage the connection objects returned by .connect.
As can be seen here: "Use of the trackable class is not recommended for new code"
Perhaps choose to go with scoped_connection or track instead.
Example:
#include <iostream>
#include <memory>
#include <boost/signals2.hpp>
struct short_lived : public boost::signals2::scoped_connection {
public:
short_lived(const boost::signals2::connection &conn) : boost::signals2::scoped_connection{conn}
{ }
~short_lived() {
std::cout << "I'm dying...1!" << std::endl;
}
};
int main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
{
/* boost::signals2::scoped_connection */ short_lived conn{s1.connect([]() {
std::cout << "Fire1!" << std::endl;
})};
s1();
}
s1();
std::cout << std::endl;
{
auto lam = []() {
std::cout << "Fire2!" << std::endl;
};
/* shared_ptr with custom deleter that does not delete (since we didn't use new),
but prints a message */
std::shared_ptr<decltype(lam)> sptr{&lam, [](decltype(lam) *) { std::cout << "I'm dying...2!" << std::endl; }};
s1.connect(sig_type::slot_type(lam).track_foreign(sptr));
s1();
}
s1();
return 0;
}
http://melpon.org/wandbox/permlink/c8LHGIp8ArkKsnWA
Found the answer referencing trackable_test.cpp:
struct short_lived : public boost::signals2::trackable {
~short_lived() {
cout << "I'm dying...!" << std::endl;
}
};
void main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
short_lived* shorty = new short_lived();
s1.connect(boost::bind<void>([](const short_lived*) {
cout << "Fire!" << std::endl;
}, shorty));
s1();
delete shorty;
s1();
}
Output
Fire!
I'm dying...!
...and a multiple params example (boost::bind refresher):
typedef boost::signals2::signal<void(int)> sig_type;
// ...same...
s1.connect(boost::bind<void>([](const short_lived*, int cannon) {
cout << "Fire " << cannon << "!" << std::endl;
}, shorty, _1));
s(1);
delete shorty;
s(2);
Output
Fire 1!
I'm dying...!
You can code something similar using shared/weak pointers:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <iostream>
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!\n");
}
};
int main() {
boost::signals2::signal<void()> signal;
{
auto test = boost::make_shared<Foo>();
signal.connect([wp = boost::weak_ptr<Foo>(test)]
{
if (auto sp = wp.lock())
sp->bar();
else
std::cout << "expired\n";
}
);
signal();
}
signal();
}
Prints
Fire!
expired
The strictly c++11 version: Live On Coliru