I have this minimal code:
#include <mutex>
#include <iostream>
std::mutex themutex;
void f1()
{
std::cout << "1" << std::endl;
std::lock_guard<std::mutex> local_mutex(themutex);
std::cout << "2" << std::endl;
}
void f2()
{
std::cout << "3" << std::endl;
std::lock_guard<std::mutex> local_mutex(themutex);
std::cout << "4" << std::endl;
f1();
std::cout << "5" << std::endl;
}
int main(void)
{
f2();
return 0;
}
I compile and run with
g++ -std=c++11 test_mutex.cc -o test_mutex && ./test_mutex
and I get this output:
3
4
1
2
5
Why?
I expect the program to lock after printing "1" and never to return.
From 30.4.1 ("Mutex requirements"):
The expression m.lock() shall be well-formed and have the following semantics:
Requires: If m is of type std::mutex or std::timed_mutex, the calling thread does not own the mutex.
You're violating the requirements, and so you cannot expect any behaviour guaranteed by the standard.
Related
I have code using mutex for self learning.
Link is : https://baptiste-wicht.com/posts/2012/04/c11-concurrency-tutorial-advanced-locking-and-condition-variables.html
I wrote the example: main_deadlock.cpp
#include <iostream>
#include <thread>
#include <mutex>
struct Complex {
std::mutex mutex;
int i;
Complex() : i(0) {}
void mul(int x){
std::cout << "mul : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "mul : after lock_guard, before operation" << std::endl;
i *= x;
std::cout << "mul : after operation" << std::endl;
}
void div(int x){
std::cout << "div : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "div : after lock_guard, before operation" << std::endl;
i /= x;
std::cout << "div : after operation" << std::endl;
}
void both(int x, int y)
{
std::cout << "both : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "both : after lock_guard, before mul()" << std::endl;
mul(x);
std::cout << "both : after mul(), before div()" << std::endl;
div(y);
std::cout << "both : after div()" << std::endl;
}
};
int main(){
std::cout << "main : starting" << std::endl;
Complex complex;
std::cout << "main : calling both()" << std::endl;
complex.both(32, 23);
return 0;
}
I would expect this code will have a deadlock when calling mul() from both() cause both() already acquire the mutex, so mul() should be blocked.
Now I am using: ubuntu 17.10.1 with g++ (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0 (g++ --version output)
If I am using the compile command:
user#user: g++ -o out_deadlock main_deadlock.cpp
I get no deadlock at all!
But if I use the compile command:
user#user: g++ -std=c++11 -pthread -o out_deadlock main_deadlock.cpp
All works - means I see deadlock.
Can you explain?
also, How the first command makes the code compile? I didn't "mention" pthreads and didn't mention -std=c++11 although code is using c++ 11 lib? I would expect fail of compilation/linkage?
Thanks.
The answer is that if you do not compile and link with -pthread then you are not using actual pthread locking functions.
The GNU Linux C library is set up that way so that libraries can call all of the locking functions, but unless they are actually linked into a multithreaded program, none of the locks actually happen.
#include <iostream>
#include <cstring>
int main()
{
const char *str = "Hello world";
char *str1 = nullptr;
std::cout << str << std::endl; // when i output to screan i see hello world
std::cout << str1 << std::endl; // when i output to scream i sen nothing
str1 = new char[strlen(str) + 1];
strcpy(str1, str);
std::cout << str << std::endl; // when i output to scream again i sen nothing
std::cout << str1 << std::endl; // The same
}
When I run it on the terminal it works fine but the loop. The for loop just doesn't do anything at all. I'm learning C++, so I don't know much.
#include <iostream>
#include <cstring>
using namespace std;
int main( int argc, char *argv[] ) {
if (argc == 2) {
cout << "The first argument is " << argv[0] << endl;
cout << "The second argument is " << argv[1] << endl;
} else if (argc > 2) {
cout << "Too many arguments" << endl;
exit(0);
} else {
cout << "Only one argument" << endl;
cout << "The argument is " << argv[0] << endl;
exit(0);
}
if (atoi(argv[1]) < 0) {
cout << "Error negative number" << endl;
exit(0);
}
// this loop does not work, everything else does.
for (int i = 1; i >= atoi(argv[1]); i++){
int count = atoi(argv[1]--);
cout << count << endl;
int sum = sum + i;
}
cout << "The sum is: " << endl;
return(0);}
I think that could be the if statements what are messing around with the loop.
I think you made mistake in the for loop.
You show use "<=" instead of ">=" in the for loop.
Hope this might helps you.
I guess your code is not reaching the for loop as you have exit() conditions on each and every condition of if. Your code only reaches the loop if you are passing 2 arguments in the terminal while you are running your code
I was doing some testing with for_each and the use of lambda functions and I'm stuck on this (compiled with g++ -std=c++11, gcc version 5.3.1)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vi = {1,1,1,1};
int end =0;
cout << "vi contains: ";
for_each(vi.begin(), vi.end(),[](int i){
cout << i << " ";
});
cout << endl;
for_each(vi.begin(),vi.end(),[&](int i){
cout << "i="<<i<<" ";
if(i==1){
vi.push_back(1);
end++;
}
});
cout << endl;
cout << "end=" << end << endl;
cout << "now vi contains: ";
for_each(vi.begin(), vi.end(),[](int i){
cout << i << " ";
});
cout << endl;
return 0;
}
and this is the output of this code
vi contains: 1 1 1 1
i=1 **i=0** i=1 i=1
end=3
now vi contains: 1 1 1 1 1 1 1
why is, at the first iteration of the loop, i equal to 0?
I understand that nearbyint allows me to round integers without throwing exceptions. It is possible to use feclearexcept to check for errors or see if rounding took place (which will always be the case for nearbyint).
Can anyone show me an example of when an exception would have been thrown which has been avoided by using nearbyint?
Here is an example of the normal use of the function:
#include <cfenv>
#include <cmath>
#include <iostream>
void test(const char* title, int round_mode)
{
std::feclearexcept(FE_ALL_EXCEPT);
std::fesetround(round_mode);
std::cout << title << std::endl;
std::cout << "nearbyint(2.5) = " << std::nearbyint(2.5) << std::endl;
std::cout << "nearbyint(-2.5) = " << std::nearbyint(-2.5) << std::endl;
std::cout << "FE_INEXACT = " << std::boolalpha << (std::fetestexcept(FE_INEXACT) != 0) << std::endl << std::endl; // This will always be true.
}
#define test(mode) test(#mode, mode)
int main()
{
#ifdef FE_DOWNWARD
test(FE_DOWNWARD);
#endif
#ifdef FE_TONEAREST
test(FE_TONEAREST);
#endif
#ifdef FE_TOWARDZERO
test(FE_TOWARDZERO);
#endif
#ifdef FE_UPWARD
test(FE_UPWARD);
#endif
}