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)22lock_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)45call_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()53get_int() { 54 return 567; 55 } 56 main()57int 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