From 6986c73651729ae46244df5cd470c0ec4b52b38d Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sun, 3 Apr 2022 14:06:36 -0400 Subject: [PATCH] [cpp] Add example of using condition_variables --- cpp/multithreading/CMakeLists.txt | 1 + cpp/multithreading/conditions/CMakeLists.txt | 26 ++++++++ cpp/multithreading/conditions/driver.cpp | 62 ++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 cpp/multithreading/conditions/CMakeLists.txt create mode 100644 cpp/multithreading/conditions/driver.cpp diff --git a/cpp/multithreading/CMakeLists.txt b/cpp/multithreading/CMakeLists.txt index fc9e2b8..f04f838 100644 --- a/cpp/multithreading/CMakeLists.txt +++ b/cpp/multithreading/CMakeLists.txt @@ -15,6 +15,7 @@ project( LANGUAGES CXX ) +add_subdirectory(conditions) add_subdirectory(deadlock) add_subdirectory(livelock) add_subdirectory(race-condition) diff --git a/cpp/multithreading/conditions/CMakeLists.txt b/cpp/multithreading/conditions/CMakeLists.txt new file mode 100644 index 0000000..af82c09 --- /dev/null +++ b/cpp/multithreading/conditions/CMakeLists.txt @@ -0,0 +1,26 @@ +################################################################################ +## Author: Shaun Reed ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of condition_variables in multithreaded C++ ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ + +cmake_minimum_required(VERSION 3.16) + +# std::scoped_lock requires C++17 +set(CMAKE_CXX_STANDARD 17) +add_compile_options("-Wall") + +project( + #[[NAME]] ConditionVariables + VERSION 1.0 + DESCRIPTION "Example of condition_variables in multithreaded C++" + LANGUAGES CXX +) + +add_executable( + multithread-conditions driver.cpp +) + +target_link_libraries(multithread-conditions pthread) diff --git a/cpp/multithreading/conditions/driver.cpp b/cpp/multithreading/conditions/driver.cpp new file mode 100644 index 0000000..1dd51e4 --- /dev/null +++ b/cpp/multithreading/conditions/driver.cpp @@ -0,0 +1,62 @@ +/*############################################################################## +## Author: Shaun Reed ## +## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## +## About: An example of condition_variables in multithreaded C++ ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +################################################################################ +*/ + +#include +#include +#include +#include +#include + +static std::mutex mtx; +std::condition_variable cv; +bool processing = false; + +// Starts a job that waits for kick-off from main +// + When job finishes, handoff result back to main via processing bool +void job(int32_t & shared) { + std::unique_lock uniqueLock(mtx); + cv.wait(uniqueLock, []()->bool {return processing;}); + std::cout << std::this_thread::get_id() + << " thread_A: Initial value of shared = " << shared << std::endl; + while (shared < INT32_MAX) { + shared++; + } + // We're no longer processing data + processing = false; + std::cout << std::this_thread::get_id() + << " thread_A: Done working." << std::endl; + uniqueLock.unlock(); // Important! Unlock uniqueLock before we notify + // Notify main that we've finished, so it can proceed + cv.notify_one(); +} + +int main(const int argc, const char * argv[]) { + std::cout << "main() thread id: " << std::this_thread::get_id() << std::endl; + + int32_t share = 0; + std::thread thread_A(job, std::ref(share)); + + mtx.lock(); + std::this_thread::sleep_for(std::chrono::seconds(3)); + share = INT32_MAX / 2; + processing = true; + mtx.unlock(); + // Notify thread_A that its work can begin + cv.notify_one(); + + // Wait until thread_A finishes its work + std::unique_lock uniqueLock(mtx); + // Block execution until we are not processing + cv.wait(uniqueLock, []()->bool { return !processing;}); + std::cout << std::this_thread::get_id() << " main(): final value of shared = " + << share << std::endl; + thread_A.join(); + + return 0; +}