David Blume commited on 2016-10-16 20:24:34
Showing 11 changed files, with 111 additions and 26 deletions.
... | ... |
@@ -9,10 +9,13 @@ $(SUBDIRS): |
9 | 9 |
$(MAKE) -C $@ |
10 | 10 |
|
11 | 11 |
all: $(LIBDIR) subdirs |
12 |
+ for dir in $(SUBDIRS); do \ |
|
13 |
+ $(MAKE) -C $$dir \ |
|
14 |
+ done |
|
12 | 15 |
|
13 | 16 |
debug: |
14 | 17 |
for dir in $(SUBDIRS); do \ |
15 |
- $(MAKE) -C $$dir debug; \ |
|
18 |
+ $(MAKE) -C $$dir $(MAKECMDGOALS); \ |
|
16 | 19 |
done |
17 | 20 |
|
18 | 21 |
product: my_lib |
... | ... |
@@ -22,5 +25,5 @@ $(LIBDIR): |
22 | 25 |
|
23 | 26 |
clean: |
24 | 27 |
for dir in $(SUBDIRS); do \ |
25 |
- $(MAKE) -C $$dir clean; \ |
|
28 |
+ $(MAKE) -C $$dir $(MAKECMDGOALS); \ |
|
26 | 29 |
done |
... | ... |
@@ -6,14 +6,14 @@ LDFLAGS=-pthread -L $(LIBDIR) -lmy_lib |
6 | 6 |
OBJDIR=obj |
7 | 7 |
|
8 | 8 |
SOURCES=main.cpp main_helper.cpp ui/widget.cpp scoped_set_adder.cpp \ |
9 |
- thread_with_lambda.cpp thread_manager.cpp |
|
9 |
+ thread_with_lambda.cpp thread_manager.cpp deadlock/deadlock.cpp |
|
10 | 10 |
# //OBJECTS=$(OBJDIR)$(SOURCES:.cpp=.o) |
11 | 11 |
OBJECTS=$(foreach bname, $(basename $(SOURCES)), $(OBJDIR)/$(bname).o) |
12 |
-EXECUTABLE=main |
|
12 |
+EXECUTABLE=testcode |
|
13 | 13 |
|
14 | 14 |
all: $(EXECUTABLE) |
15 | 15 |
|
16 |
-debug: CPPFLAGS += -g |
|
16 |
+debug: CPPFLAGS += -DDEBUG -ggdb |
|
17 | 17 |
debug: $(EXECUTABLE) |
18 | 18 |
|
19 | 19 |
$(OBJDIR): |
... | ... |
@@ -22,10 +22,13 @@ $(OBJDIR): |
22 | 22 |
$(OBJDIR)/ui: |
23 | 23 |
mkdir $@ |
24 | 24 |
|
25 |
+$(OBJDIR)/deadlock: |
|
26 |
+ mkdir $@ |
|
27 |
+ |
|
25 | 28 |
$(EXECUTABLE): $(OBJECTS) $(LIBDIR)/libmy_lib.a |
26 | 29 |
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@ |
27 | 30 |
|
28 |
-$(OBJDIR)/%.o: %.cpp ../include/my_lib.hpp | $(OBJDIR) $(OBJDIR)/ui |
|
31 |
+$(OBJDIR)/%.o: %.cpp ../include/my_lib.hpp | $(OBJDIR) $(OBJDIR)/ui $(OBJDIR)/deadlock |
|
29 | 32 |
$(CXX) $(CPPFLAGS) $< -o $@ |
30 | 33 |
|
31 | 34 |
clean: |
... | ... |
@@ -0,0 +1,85 @@ |
1 |
+#include <iostream> |
|
2 |
+#include <string> |
|
3 |
+#include <vector> |
|
4 |
+#include <thread> |
|
5 |
+#include <mutex> |
|
6 |
+#include <unistd.h> |
|
7 |
+#include <random> |
|
8 |
+#include <chrono> |
|
9 |
+#include "deadlock.hpp" |
|
10 |
+ |
|
11 |
+using namespace std; |
|
12 |
+ |
|
13 |
+namespace { |
|
14 |
+ |
|
15 |
+std::mutex left_chopstick; |
|
16 |
+std::mutex right_chopstick; |
|
17 |
+ |
|
18 |
+std::vector<std::thread> workers; |
|
19 |
+ |
|
20 |
+void do_work_on_right(bool, int32_t); |
|
21 |
+ |
|
22 |
+int get_rnd() |
|
23 |
+{ |
|
24 |
+ static std::random_device rd; |
|
25 |
+ static std::mt19937 gen(rd()); |
|
26 |
+ static std::uniform_int_distribution<> dis(100, 200); |
|
27 |
+ return dis(gen); |
|
28 |
+} |
|
29 |
+ |
|
30 |
+void do_work_on_left(bool have_right, int32_t tick) |
|
31 |
+{ |
|
32 |
+ std::lock_guard<std::mutex> lm (left_chopstick); |
|
33 |
+ std::this_thread::sleep_for(std::chrono::milliseconds(get_rnd())); |
|
34 |
+ if (have_right) { |
|
35 |
+ std::cout << "deadlock::thread " << std::hex << this_thread::get_id() << " " << tick << endl; |
|
36 |
+ } else { |
|
37 |
+ do_work_on_right(true, tick); |
|
38 |
+ } |
|
39 |
+} |
|
40 |
+ |
|
41 |
+void do_work_on_right(bool have_left, int32_t tick) |
|
42 |
+{ |
|
43 |
+ std::lock_guard<std::mutex> rm (right_chopstick); |
|
44 |
+ std::this_thread::sleep_for(std::chrono::milliseconds(get_rnd())); |
|
45 |
+ if (have_left) { |
|
46 |
+ std::cout << "deadlock::thread " << std::hex << this_thread::get_id() << " " << tick << endl; |
|
47 |
+ } else { |
|
48 |
+ do_work_on_left(true, tick); |
|
49 |
+ } |
|
50 |
+} |
|
51 |
+ |
|
52 |
+void work(int32_t ticks) |
|
53 |
+{ |
|
54 |
+ for(int32_t tick = ticks; tick >= 0; tick--) { |
|
55 |
+ do_work_on_right(false, tick); |
|
56 |
+ } |
|
57 |
+} |
|
58 |
+ |
|
59 |
+}; |
|
60 |
+ |
|
61 |
+int deadlock() |
|
62 |
+{ |
|
63 |
+ uint32_t ticks = 10; |
|
64 |
+ cout << "The function " << __PRETTY_FUNCTION__ << " was called." << endl; |
|
65 |
+ cerr << "WARNING: Expect a deadlock. See http://wiki.dlma.com/gdb" << endl; |
|
66 |
+ |
|
67 |
+ // Construct the thread right into the push_back() call. |
|
68 |
+ workers.push_back(std::thread([=]{ |
|
69 |
+ for(uint32_t tick = 0; tick <= ticks; tick++) { |
|
70 |
+ do_work_on_left(false, tick); |
|
71 |
+ // usleep(get_rnd() * 1000); // u for microseconds |
|
72 |
+ } |
|
73 |
+ })); |
|
74 |
+ |
|
75 |
+ // Or, move the thread into the array. |
|
76 |
+ std::thread t2(work, ticks); |
|
77 |
+ workers.push_back(move(t2)); |
|
78 |
+ |
|
79 |
+ // Don't return before the other threads have finished. |
|
80 |
+ for (auto &w : workers) { |
|
81 |
+ if (w.joinable()) w.join(); |
|
82 |
+ } |
|
83 |
+ return 0; |
|
84 |
+} |
|
85 |
+ |
... | ... |
@@ -11,6 +11,7 @@ |
11 | 11 |
#include "../include/my_lib.hpp" |
12 | 12 |
#include "thread_with_lambda.hpp" |
13 | 13 |
#include "thread_manager.hpp" |
14 |
+#include "deadlock/deadlock.hpp" |
|
14 | 15 |
|
15 | 16 |
using namespace std; |
16 | 17 |
|
... | ... |
@@ -116,6 +117,8 @@ int main() { |
116 | 117 |
my_class->f(); |
117 | 118 |
} |
118 | 119 |
|
120 |
+ deadlock(); |
|
121 |
+ |
|
119 | 122 |
// This_function_is_not_defined(); |
120 | 123 |
|
121 | 124 |
cout << "Done." << endl; |
... | ... |
@@ -15,11 +15,11 @@ void thread_with_lambda() |
15 | 15 |
{ |
16 | 16 |
uint32_t ticks = 10; |
17 | 17 |
std::lock_guard<std::mutex> lock(my_mutex); |
18 |
- if (worker.joinable()) worker.join(); |
|
19 | 18 |
|
20 | 19 |
worker = std::thread([=]{ |
21 | 20 |
for(uint32_t tick = 0; tick <= ticks; tick++) { |
22 |
- std::cout << "count " << tick << std::endl; |
|
21 |
+ std::cout << __PRETTY_FUNCTION__ << " count " << tick << std::endl; |
|
23 | 22 |
} |
24 | 23 |
}); |
24 |
+ if (worker.joinable()) worker.join(); |
|
25 | 25 |
} |