In this article we will discuss how to stop or terminate a thread in C++11.

C++11 does not provides a direct method to stop a running thread and that’s because that thread might have some resources to release or close before exit i.e.

What if a thread has acquired a lock and we kill that thread suddenly, then who’s gonna release that lock ?

What if a thread has opened a file to write the text and we stopped that thread, then who’s gonna close that file ?

What if thread has allocated memory on heap and before it could delete that memory, we stopped the thread. Then who’s gonna prevent that memory leak.

Therefore there is no direct function to close the thread. But we can notify the thread to exit and we can implement out thread in a such a way that after some interval or at some checkpoints it should check, if I am requested to exit or not. If yes then it should exit gracefully , by releasing all the resources.

Stopping a Thread using std::future<>

We can pass a std::future<void> object to thread and thread should exit when value in future is available. As, we want to only signal the thread and not actually passing any value in that signal, so we will can use future object of type void.

Let’s create a promise object of type void in main function i.e.



// Create a std::promise object std::promise<void> exitSignal;

//Fetch std::future object associated with promise std::future<void> futureObj = exitSignal.get_future();

// Starting Thread & move the future object in lambda function by reference std::thread th(&threadFunction, std::move(futureObj));

void threadFunction(std::future<void> futureObj) { std::cout << "Thread Start" << std::endl; while (futureObj.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout) { std::cout << "Doing Some Work" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } std::cout << "Thread End" << std::endl; }

//Set the value in promise exitSignal.set_value();

#include <thread> #include <iostream> #include <assert.h> #include <chrono> #include <future> void threadFunction(std::future<void> futureObj) { std::cout << "Thread Start" << std::endl; while (futureObj.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout) { std::cout << "Doing Some Work" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } std::cout << "Thread End" << std::endl; } int main() { // Create a std::promise object std::promise<void> exitSignal; //Fetch std::future object associated with promise std::future<void> futureObj = exitSignal.get_future(); // Starting Thread & move the future object in lambda function by reference std::thread th(&threadFunction, std::move(futureObj)); //Wait for 10 sec std::this_thread::sleep_for(std::chrono::seconds(10)); std::cout << "Asking Thread to Stop" << std::endl; //Set the value in promise exitSignal.set_value(); //Wait for thread to join th.join(); std::cout << "Exiting Main Function" << std::endl; return 0; }

Thread Start Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Asking Thread to Stop Thread End Exiting Main Function

Creating a Stoppable Task

Now, fetch the associated future object from this promise in main function i.e.Now in main function while creating the thread, pass the future object to the thread function i.e.Inside the thread, we are doing some Work and keep on checking that if thread has been requested to exit i.e. value in future is available or not.As soon as we set value in promise object from main function, value in future object will available in thread function i.e.Complete example is as follows,

Creating promise and future object every time, when we want to create task that can be stopped, is a repeating task.

Let’s avoid that by creating a Stoppable class that provide all this functionality in object oriented manner.

Stoppable class that encapsulate the promise and future object



/* * Class that encapsulates promise and future object and * provides API to set exit signal for the thread */ class Stoppable { std::promise<void> exitSignal; std::future<void> futureObj; public: Stoppable() : futureObj(exitSignal.get_future()) { } Stoppable(Stoppable && obj) : exitSignal(std::move(obj.exitSignal)), futureObj(std::move(obj.futureObj)) { std::cout << "Move Constructor is called" << std::endl; } Stoppable & operator=(Stoppable && obj) { std::cout << "Move Assignment is called" << std::endl; exitSignal = std::move(obj.exitSignal); futureObj = std::move(obj.futureObj); return *this; } // Task need to provide defination for this function // It will be called by thread function virtual void run() = 0; // Thread function to be executed by thread void operator()() { run(); } //Checks if thread is requested to stop bool stopRequested() { // checks if value in future object is available if (futureObj.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout) return false; return true; } // Request the thread to stop by setting value in promise object void stop() { exitSignal.set_value(); } };

/* * A Task class that extends the Stoppable Task */ class MyTask: public Stoppable { public: // Function to be executed by thread function void run() { std::cout << "Task Start" << std::endl; // Check if thread is requested to stop ? while (stopRequested() == false) { std::cout << "Doing Some Work" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } std::cout << "Task End" << std::endl; } };

// Creating our Task MyTask task; //Creating a thread to execute our task std::thread th([&]() { task.run(); }); std::this_thread::sleep_for(std::chrono::seconds(10)); std::cout << "Asking Task to Stop" << std::endl; // Stop the Task task.stop(); //Waiting for thread to join th.join();

Learn more about multithreading in C++11 / 14

We just need to extend this class in our task class and provide definition for run() function, which will like our thread function i.e.Now lets see how to use this Stoppable task in main function i.e.

Complete example is as follows,



#include <thread> #include <iostream> #include <assert.h> #include <chrono> #include <future> /* * Class that encapsulates promise and future object and * provides API to set exit signal for the thread */ class Stoppable { std::promise<void> exitSignal; std::future<void> futureObj; public: Stoppable() : futureObj(exitSignal.get_future()) { } Stoppable(Stoppable && obj) : exitSignal(std::move(obj.exitSignal)), futureObj(std::move(obj.futureObj)) { std::cout << "Move Constructor is called" << std::endl; } Stoppable & operator=(Stoppable && obj) { std::cout << "Move Assignment is called" << std::endl; exitSignal = std::move(obj.exitSignal); futureObj = std::move(obj.futureObj); return *this; } // Task need to provide defination for this function // It will be called by thread function virtual void run() = 0; // Thread function to be executed by thread void operator()() { run(); } //Checks if thread is requested to stop bool stopRequested() { // checks if value in future object is available if (futureObj.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout) return false; return true; } // Request the thread to stop by setting value in promise object void stop() { exitSignal.set_value(); } }; /* * A Task class that extends the Stoppable Task */ class MyTask: public Stoppable { public: // Function to be executed by thread function void run() { std::cout << "Task Start" << std::endl; // Check if thread is requested to stop ? while (stopRequested() == false) { std::cout << "Doing Some Work" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } std::cout << "Task End" << std::endl; } }; int main() { // Creating our Task MyTask task; //Creating a thread to execute our task std::thread th([&]() { task.run(); }); std::this_thread::sleep_for(std::chrono::seconds(10)); std::cout << "Asking Task to Stop" << std::endl; // Stop the Task task.stop(); //Waiting for thread to join th.join(); std::cout << "Thread Joined" << std::endl; std::cout << "Exiting Main Function" << std::endl; return 0; }

Task Start Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Doing Some Work Asking Task to Stop Task End Thread Joined Exiting Main Function