Skip to content

Commit adfb4f0

Browse files
committed
CPP test case
1 parent af0d076 commit adfb4f0

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.cpp:30:5:30:6 | d2 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.cpp:31:41:31:49 | call to lock_guard | lock 1 | test.cpp:36:39:36:45 | call to lock_guard | lock 2 |
2+
| test.cpp:44:5:44:6 | d3 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.cpp:45:41:45:49 | call to lock_guard | lock 1 | test.cpp:50:39:50:45 | call to lock_guard | lock 2 |
3+
| test.cpp:86:5:86:6 | d5 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.cpp:103:41:103:49 | call to lock_guard | lock 1 | test.cpp:104:39:104:45 | call to lock_guard | lock 2 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <mutex>
2+
#include <stdlib.h>
3+
#include <thread>
4+
5+
class B {
6+
int sum;
7+
8+
public:
9+
std::mutex mu;
10+
B() = delete;
11+
explicit B(int initialAmount) : sum(initialAmount) {}
12+
int get() const { return sum; }
13+
void set(int amount) { sum = amount; }
14+
};
15+
16+
int d1(B *from, B *to, int amount) { // COMPLIANT
17+
std::unique_lock<std::mutex> lk1(from->mu, std::defer_lock);
18+
std::unique_lock<std::mutex> lk2(to->mu, std::defer_lock);
19+
20+
std::lock(lk1, lk2);
21+
22+
if (from->get() >= amount) {
23+
from->set(from->get() - amount);
24+
to->set(to->get() + amount);
25+
return 0;
26+
}
27+
return -1;
28+
}
29+
30+
int d2(B *from, B *to, int amount) { // NON_COMPLIANT
31+
std::lock_guard<std::mutex> from_lock(from->mu);
32+
33+
if (from->get() < amount) {
34+
return -1;
35+
}
36+
std::lock_guard<std::mutex> to_lock(to->mu);
37+
38+
from->set(from->get() - amount);
39+
to->set(to->get() + amount);
40+
41+
return 0;
42+
}
43+
44+
int d3(B *from, B *to, int amount) { // NON_COMPLIANT
45+
std::lock_guard<std::mutex> from_lock(from->mu);
46+
47+
if (from->get() < amount) {
48+
return -1;
49+
}
50+
std::lock_guard<std::mutex> to_lock(to->mu);
51+
52+
from->set(from->get() - amount);
53+
to->set(to->get() + amount);
54+
55+
return 0;
56+
}
57+
58+
int getA() { return 0; }
59+
60+
int d4(B *from, B *to, int amount) { // COMPLIANT
61+
std::mutex *one;
62+
std::mutex *two;
63+
64+
int a = getA();
65+
66+
// here a may take on multiple different
67+
// values and thus different values may flow
68+
// into the locks
69+
if (a == 9) {
70+
one = &from->mu;
71+
two = &to->mu;
72+
} else {
73+
one = &to->mu;
74+
two = &from->mu;
75+
}
76+
77+
std::lock_guard<std::mutex> from_lock(*one);
78+
std::lock_guard<std::mutex> to_lock(*two);
79+
80+
from->set(from->get() - amount);
81+
to->set(to->get() + amount);
82+
83+
return 0;
84+
}
85+
86+
int d5(B *from, B *to, int amount) { // NON_COMPLIANT
87+
std::mutex *one;
88+
std::mutex *two;
89+
90+
int a = getA();
91+
92+
// here a may take on multiple different
93+
// values and thus different values may flow
94+
// into the locks
95+
if (a == 9) {
96+
one = &from->mu;
97+
two = &to->mu;
98+
} else {
99+
one = &to->mu;
100+
two = &from->mu;
101+
}
102+
103+
std::lock_guard<std::mutex> from_lock(from->mu);
104+
std::lock_guard<std::mutex> to_lock(to->mu);
105+
106+
from->set(from->get() - amount);
107+
to->set(to->get() + amount);
108+
109+
return 0;
110+
}
111+
112+
void f(B *ba1, B *ba2) {
113+
std::thread thr1(d1, ba1, ba2, 100);
114+
std::thread thr2(d1, ba2, ba1, 100);
115+
thr1.join();
116+
thr2.join();
117+
}
118+
119+
void f2(B *ba1, B *ba2) {
120+
std::thread thr1(d2, ba1, ba2, 100);
121+
std::thread thr2(d2, ba2, ba1, 100);
122+
thr1.join();
123+
thr2.join();
124+
}
125+
126+
void f3(B *ba1, B *ba2) {
127+
std::thread thr1(d3, ba1, ba2, 100);
128+
std::thread thr2(d3, ba1, ba2, 100);
129+
thr1.join();
130+
thr2.join();
131+
}
132+
133+
void f4(B *ba1, B *ba2) {
134+
std::thread thr1(d4, ba1, ba2, 100);
135+
std::thread thr2(d4, ba1, ba2, 100);
136+
thr1.join();
137+
thr2.join();
138+
}
139+
140+
void f5(B *ba1, B *ba2) {
141+
std::thread thr1(d5, ba1, ba2, 100);
142+
std::thread thr2(d5, ba1, ba2, 100);
143+
thr1.join();
144+
thr2.join();
145+
}

0 commit comments

Comments
 (0)