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:
ItemKeeper()19 ItemKeeper() { }
20
doSomething()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
threadFunc(int invokerID,bool & exceptionOccurred)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
main(int argc,char * argv[])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( "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(exceptionOccurred1));
66 boost::thread thread2(threadFunc, 2, boost::ref(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(timeout)) {
75 deadlockOccured = true;
76 thread1.interrupt();
77 }
78 if (!thread2.timed_join(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