1 | // Copyright (C) 2012 Vicente Botet |
---|---|
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #define BOOST_THREAD_VERSION 2 |
7 | |
8 | #include <boost/date_time.hpp> |
9 | #include <boost/thread/mutex.hpp> |
10 | #include <boost/thread/thread_only.hpp> |
11 | #include <iostream> |
12 | |
13 | // Number should be big enough to allow context switch between threads, otherwise the bug doesn't show. |
14 | static int MAX_COUNTS; |
15 | |
16 | class ItemKeeper { |
17 | |
18 | public: |
19 | ItemKeeper() { } |
20 | |
21 | void doSomething() { |
22 | boost::unique_lock<boost::mutex> scoped_lock(mutex); |
23 | int counts = MAX_COUNTS; |
24 | while (counts--); |
25 | } |
26 | |
27 | private: |
28 | boost::mutex mutex; |
29 | }; |
30 | |
31 | ItemKeeper itemKeeper; |
32 | |
33 | int MAX_ITERATIONS(5); |
34 | |
35 | void threadFunc(int invokerID, bool& exceptionOccurred) { |
36 | try { |
37 | for (int i = 0; i < MAX_ITERATIONS; i++) { |
38 | std::cout << "Thread "<< invokerID << ", iteration "<< i << std::endl; |
39 | itemKeeper.doSomething(); |
40 | } |
41 | } catch (...) { |
42 | exceptionOccurred = true; |
43 | } |
44 | } |
45 | |
46 | |
47 | int main(int argc, char* argv[]) { |
48 | if (argc < 2) { |
49 | MAX_COUNTS = 5000000; |
50 | } else { |
51 | std::string valueStr(argv[1]); |
52 | bool has_only_digits = (valueStr.find_first_not_of( s: "0123456789") == std::string::npos); |
53 | if (has_only_digits) { |
54 | std::istringstream aStream(valueStr); |
55 | aStream >> MAX_COUNTS; |
56 | } else { |
57 | std::cerr << "Argument should be an integer\n"; |
58 | return 1; |
59 | } |
60 | } |
61 | |
62 | bool exceptionOccurred1(false); |
63 | bool exceptionOccurred2(false); |
64 | |
65 | boost::thread thread1(threadFunc, 1, boost::ref(t&: exceptionOccurred1)); |
66 | boost::thread thread2(threadFunc, 2, boost::ref(t&: exceptionOccurred2)); |
67 | |
68 | boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(10000*100); |
69 | |
70 | bool deadlockOccured(false); |
71 | //thread1.join(); |
72 | //thread2.join(); |
73 | |
74 | if (!thread1.timed_join(rel_time: timeout)) { |
75 | deadlockOccured = true; |
76 | thread1.interrupt(); |
77 | } |
78 | if (!thread2.timed_join(rel_time: timeout)) { |
79 | deadlockOccured = true; |
80 | thread2.interrupt(); |
81 | } |
82 | |
83 | if (deadlockOccured) { |
84 | std::cout << "Deadlock occurred\n"; |
85 | return 1; |
86 | } |
87 | if (exceptionOccurred1 || exceptionOccurred2) { |
88 | std::cout << "Exception occurred\n"; |
89 | return 1; |
90 | } |
91 | return 0; |
92 | } |
93 | |
94 |