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