1 // Copyright (C) 2013 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 ////////////////////////////////////////////
7 
8 //#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
9 #include <iostream>
10 #include <boost/thread/thread_only.hpp>
11 #include <boost/thread/shared_mutex.hpp>
12 // shared_mutex_deadlock.cpp : Defines the entry point for the console application.
13 //
14 
15 
16 boost::shared_mutex mutex;
17 
thread2_func()18 void thread2_func()
19 {
20   int i (0);
21   for (;;)
22   {
23     if (mutex.timed_lock(boost::posix_time::milliseconds(500)))
24     {
25       std::cout << "Unique lock acquired" << std::endl
26         << "Test successful" << std::endl;
27       mutex.unlock();
28       break;
29     }
30     ++i;
31     if (i == 100)
32     {
33       std::cout << "Test failed. App is deadlocked" << std::endl;
34       break;
35     }
36     boost::this_thread::sleep(boost::posix_time::seconds(1));
37   }
38 }
39 
thread3_func()40 void thread3_func()
41 {
42   boost::shared_lock<boost::shared_mutex> lock (mutex);
43   std::cout << "Shared lock acquired" << std::endl
44         << "Test successful" << std::endl;
45 }
46 
thread3_func_workaround()47 void thread3_func_workaround()
48 {
49   for (;;)
50   {
51     if (mutex.timed_lock_shared(boost::posix_time::milliseconds(200)))
52     {
53       std::cout << "Shared lock acquired" << std::endl
54         << "Test successful" << std::endl;
55       mutex.unlock_shared();
56       break;
57     }
58     boost::this_thread::sleep(boost::posix_time::milliseconds(100));
59   }
60 }
61 
main()62 int main()
63 {
64   std::cout << "Starting" << std::endl;
65 
66   // 1 - lock the mutex
67   boost::shared_lock<boost::shared_mutex> lock (mutex);
68 
69   // 2 - start thread#2
70   boost::thread thread2(&thread2_func);
71 
72   // 3 - sleep
73   boost::this_thread::sleep(boost::posix_time::milliseconds(10));
74 
75   std::cout << "Thread#2 is waiting" << std::endl;
76 
77   // - start thread3
78   boost::thread thread3(&thread3_func);
79   //boost::thread thread3(&thread3_func_workaround);
80 
81   std::cout << "Thread#3 is started and blocked. It never will waked" << std::endl;
82 
83   thread3.join(); // will never return
84 
85   lock.unlock(); // release shared ownership. thread#2 will take unique ownership
86 
87   thread2.join();
88 
89   std::cout << "Finished" << std::endl;
90   return 0;
91 }
92 
93 
94 
95