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