1 | #include <iostream>
|
---|
2 | #include <boost/shared_ptr.hpp>
|
---|
3 | #include <boost/bind.hpp>
|
---|
4 | #include <boost/thread/condition.hpp>
|
---|
5 | #include <boost/thread/recursive_mutex.hpp>
|
---|
6 | #include <boost/thread/thread.hpp>
|
---|
7 |
|
---|
8 | //---------------------------------------------------------------------------
|
---|
9 |
|
---|
10 | class Activity {
|
---|
11 | public:
|
---|
12 | virtual ~Activity();
|
---|
13 | virtual void Execute();
|
---|
14 |
|
---|
15 | protected:
|
---|
16 | virtual void PerformActivity();
|
---|
17 |
|
---|
18 | private:
|
---|
19 | void DoWork();
|
---|
20 | void SetStarted();
|
---|
21 | void SyncStart();
|
---|
22 |
|
---|
23 | boost::recursive_mutex m_MutexState;
|
---|
24 | boost::condition m_ConditionState;
|
---|
25 |
|
---|
26 | bool m_IsStarted; // must use mutex to access
|
---|
27 |
|
---|
28 | boost::shared_ptr<boost::thread> m_ActivityThread;
|
---|
29 | };
|
---|
30 |
|
---|
31 | //---------------------------------------------------------------------------
|
---|
32 |
|
---|
33 | Activity::~Activity()
|
---|
34 | {
|
---|
35 | }
|
---|
36 |
|
---|
37 | //---------------------------------------------------------------------------
|
---|
38 |
|
---|
39 | void Activity::DoWork()
|
---|
40 | {
|
---|
41 | SetStarted();
|
---|
42 |
|
---|
43 | // additional code removed for brevity
|
---|
44 | }
|
---|
45 |
|
---|
46 | //---------------------------------------------------------------------------
|
---|
47 |
|
---|
48 | // virtual
|
---|
49 | void Activity::Execute()
|
---|
50 | {
|
---|
51 | boost::recursive_mutex::scoped_lock lock(m_MutexState);
|
---|
52 |
|
---|
53 | m_IsStarted = false;
|
---|
54 | m_ActivityThread.reset(new boost::thread(boost::bind(&Activity::DoWork, this)));
|
---|
55 |
|
---|
56 | SyncStart();
|
---|
57 | }
|
---|
58 |
|
---|
59 | //---------------------------------------------------------------------------
|
---|
60 |
|
---|
61 | void Activity::PerformActivity()
|
---|
62 | {
|
---|
63 | std::cout << "Hello world!";
|
---|
64 | }
|
---|
65 |
|
---|
66 | //---------------------------------------------------------------------------
|
---|
67 |
|
---|
68 | void Activity::SetStarted()
|
---|
69 | {
|
---|
70 | // Thread 2 deadlocks here
|
---|
71 | boost::recursive_mutex::scoped_lock lock(m_MutexState);
|
---|
72 |
|
---|
73 | m_IsStarted = true;
|
---|
74 | m_ConditionState.notify_all();
|
---|
75 | }
|
---|
76 |
|
---|
77 | //---------------------------------------------------------------------------
|
---|
78 |
|
---|
79 | void Activity::SyncStart()
|
---|
80 | {
|
---|
81 | boost::recursive_mutex::scoped_lock lock(m_MutexState);
|
---|
82 |
|
---|
83 | while (!m_IsStarted) {
|
---|
84 | // Thread 1 deadlocks here
|
---|
85 | m_ConditionState.wait(lock);
|
---|
86 | }
|
---|
87 | }
|
---|
88 |
|
---|
89 | //---------------------------------------------------------------------------
|
---|
90 |
|
---|
91 | int main()
|
---|
92 | {
|
---|
93 | Activity activity;
|
---|
94 |
|
---|
95 | activity.Execute();
|
---|
96 | }
|
---|