c:c_threads:event_handling
Table of Contents
C - C++ Threads - Event Handling
To have a thread wait for an event to happen like a condition to become true or a task to be completed by another thread.
Option 1 - Use a boolean global variable
Two threads:
- thread1 performs some actions, then sets a flag.
- thread2 is waiting for this flag to be set.
#include<iostream> #include<thread> #include<mutex> class Application { std::mutex m_mutex; bool m_bDataLoaded; public: Application() { m_bDataLoaded = false; } void loadData() { // Make This Thread sleep for 1 Second. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout<<"Loading Data from XML"<<std::endl; // Lock The Data structure. std::lock_guard<std::mutex> guard(m_mutex); // Set the flag to true, means data is loaded. m_bDataLoaded = true; } void mainTask() { std::cout<<"Do Some Handshaking"<<std::endl; // Acquire the Lock. m_mutex.lock(); // Check if flag is set to true or not. while(m_bDataLoaded != true) { // Release the lock. m_mutex.unlock(); // Sleep for 100 milliseconds. std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Acquire the lock m_mutex.lock(); } // Release the lock. m_mutex.unlock(); // Doc processing on loaded Data. std::cout<<"Do Processing On loaded Data"<<std::endl; } }; int main() { Application app; std::thread thread_1(&Application::mainTask, &app); std::thread thread_2(&Application::loadData, &app); thread_2.join(); thread_1.join(); return 0; }
NOTE: It has following disadvantages:
- Thread will keep on acquiring the lock and releasing it just to check the value, therefore it will consume CPU cycles and will also make Thread 1 slow, because it needs to acquire same lock to update the bool flag.
A better choice is to use Condition Variables; which is a kind of Event used for signaling between two or more threads. One or more thread can wait on it to get signaled, while an another thread can signal it.
Option 2 - Using a Condition Variable
#include <iostream> #include <thread> #include <functional> #include <mutex> #include <condition_variable> using namespace std::placeholders; class Application { std::mutex m_mutex; std::condition_variable m_condVar; bool m_bDataLoaded; public: Application() { m_bDataLoaded = false; } void loadData() { // Make This Thread sleep for 1 Second. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout<<"Loading Data from XML"<<std::endl; // Lock The Data structure. std::lock_guard<std::mutex> guard(m_mutex); // Set the flag to true, means data is loaded. m_bDataLoaded = true; // Notify the condition variable. m_condVar.notify_one(); } bool isDataLoaded() { return m_bDataLoaded; } void mainTask() { std::cout<<"Do Some Handshaking"<<std::endl; // Acquire the lock std::unique_lock<std::mutex> mlock(m_mutex); // Start waiting for the Condition Variable to get signaled // Wait() will internally release the lock and make the thread to block // As soon as condition variable get signaled, resume the thread and // again acquire the lock. Then check if condition is met or not // If condition is met then continue else again go in wait. m_condVar.wait(mlock, std::bind(&Application::isDataLoaded, this)); std::cout<<"Do Processing On loaded Data"<<std::endl; } }; int main() { Application app; std::thread thread_1(&Application::mainTask, &app); std::thread thread_2(&Application::loadData, &app); thread_2.join(); thread_1.join(); return 0; }
c/c_threads/event_handling.txt · Last modified: 2021/06/09 11:04 by peter