1 #include <stdio.h>
2 #include <thread>
3 #include <mutex>
4 #include <condition_variable>
5 
6 std::mutex contended_mutex;
7 
8 std::mutex control_mutex;
9 std::condition_variable  control_condition;
10 
11 std::mutex thread_started_mutex;
12 std::condition_variable  thread_started_condition;
13 
14 // This function runs in a thread.  The locking dance is to make sure that
15 // by the time the main thread reaches the pthread_join below, this thread
16 // has for sure acquired the contended_mutex.  So then the call_me_to_get_lock
17 // function will block trying to get the mutex, and only succeed once it
18 // signals this thread, then lets it run to wake up from the cond_wait and
19 // release the mutex.
20 
21 void
lock_acquirer_1(void)22 lock_acquirer_1 (void)
23 {
24   std::unique_lock<std::mutex> contended_lock(contended_mutex);
25 
26   // Grab this mutex, that will ensure that the main thread
27   // is in its cond_wait for it (since that's when it drops the mutex.
28 
29   thread_started_mutex.lock();
30   thread_started_mutex.unlock();
31 
32   // Now signal the main thread that it can continue, we have the contended lock
33   // so the call to call_me_to_get_lock won't make any progress till  this
34   // thread gets a chance to run.
35 
36   std::unique_lock<std::mutex> control_lock(control_mutex);
37 
38   thread_started_condition.notify_all();
39 
40   control_condition.wait(control_lock);
41 
42 }
43 
44 int
call_me_to_get_lock(int ret_val)45 call_me_to_get_lock (int ret_val)
46 {
47   control_condition.notify_all();
48   contended_mutex.lock();
49   return ret_val;
50 }
51 
52 int
get_int()53 get_int() {
54   return 567;
55 }
56 
main()57 int main ()
58 {
59   std::unique_lock<std::mutex> thread_started_lock(thread_started_mutex);
60 
61   std::thread thread_1(lock_acquirer_1);
62 
63   thread_started_condition.wait(thread_started_lock);
64 
65   control_mutex.lock();
66   control_mutex.unlock();
67 
68   // Break here.  At this point the other thread will have the contended_mutex,
69   // and be sitting in its cond_wait for the control condition.  So there is
70   // no way that our by-hand calling of call_me_to_get_lock will proceed
71   // without running the first thread at least somewhat.
72 
73   int result = call_me_to_get_lock(get_int());
74   thread_1.join();
75 
76   return 0;
77 
78 }
79