C++

How do you kill a Thread in C++?

Well, you should not kill a thread in its execution for the following reasons:

  • A thread might have opened a file for writing, and if it is killed, the file would not be closed. That is trouble.
  • A thread might have acquired a lock on computer resources for its sole use. If the thread is killed, the resources will remain locked, and other threads and processes will not be able to use the resources.
  • Memory allocated has to be released. The thread might have allocated some memory for some purpose. If the thread is killed, the memory will remain falsely allocated and unavailable for other threads and processes. That is a memory leak.

These reasons and any other means that, if a thread is killed, resources that it might have acquired would not be released for use by other threads and processes. When a thread completes naturally, any resource acquired is released.

The typical motive for killing a thread is that the user no longer needs the result of the thread.

There is some good news: C++20 is the latest version of C++ today. The thread class of C++20 has components to release the resources, of a thread, before its natural end and stop it before its natural end. In this way, C++ is stopping the thread and not killing the thread. Put another way, C++20 is killing the thread responsibly. The releasing of resources and stopping of the thread are automatic. Note: not all threads can be stopped this way. Such threads would complete naturally, even if an attempt is made to stop them.

The thread library has the following classes for stopping with the release of resources: stop_token, stop_source, and stop_callback. Each of these classes can have objects instantiated from. However, only stop_token and stop_source are considered in this tutorial.

The command to run a program of threads, with the g++ compiler, for C+20, should be similar to:

    g++ -std=c++2a temp.cpp -lpthread -o temp

This tutorial explains how to stop a thread with resources released. Stopping a thread with resources released is a responsible way of killing a thread. This tutorial begins with a summary of codding a thread.

Article Content

Thread Coding Summary

A running program in C++ is a process. A thread is a sub-process of a process. A simple C++ program has just one thread, which is the main() function. The main() function is not a formally declared thread. Any other thread for the same program must be formally declared. There can be more than one thread in a program.

A thread is instantiated from a thread class of the thread library. The first argument of the declaration of a thread object is the name of a top-level function. The top-level function is the effective thread. When the object is instantiated, the top-level function starts executing (running).

There is a calling thread and a called thread. Unfortunately, if the called thread is not joined from the function body of the called thread, the calling thread may complete its execution without the called thread having completed its own execution. This means trouble. So, the function body of the calling thread should always join the called thread after the instantiation of the called thread.

In the following program, a thread object is instantiated, using the top-level function, fn():

    #include <iostream>

    #include <thread>

    using namespace std;


    void fn() {

        cout <<"first code segment of thread" <<endl;

        cout <<"second code segment of thread" <<endl;

    }


    int main()

    {

        thread thr(fn);

        thr.join();


        return 0;

    }

The output is:

    first code segment of thread

    second code segment of thread

Note the inclusion of the thread library. Note how the first and second statements of the main function have been coded. The main() function is the main thread. fn() is a top-level function.

The jthread Class

The jthread is a class defined in the thread library. It is like the thread class but has the advantage that it can be used to stop a thread by releasing resources. It has member functions to return a stop_token object and a stop_source object. The member functions are:

    stop_source get_stop_source()

    stop_token get_stop_token()

It also has the member function to make a stop request, which is:

    bool request_stop()

As of now, in October 2021, many C++ compilers are still implementing the jthread class. However, the code samples given below should work when your compiler has implemented the jthread class.

Request to stop a Thread

Stopping the thread means stopping the top-level function from running. A request to stop means that the thread should stop as soon as possible. If the request is not granted, the thread will run to completion and not stop before its end.

As indicated above, a thread instantiated from the jthread has the features to kill a thread responsibly (stop a thread from releasing its resources). The member function to request this stop is:

    bool request_stop()

The return value is true if the request was accepted and false otherwise. Accepting the request does not guarantee that the thread will stop as soon as possible. It may not be possible to implement the request, and the thread will not stop until its natural end. That is, returning true does not mean that stopping is possible. The following program illustrates the use of this member function of the jthread object:

    #include <iostream>

    #include <thread>

    using namespace std;


    void fn() {

        cout <<"first code segment of thread" <<endl;

        cout <<"second code segment of thread" <<endl;

    }


    int main()

    {

        jthread thr(fn);

        thr.request_stop();

        thr.join();


        return 0;

    }

This program is similar to the above, but for two points:

  • The thread, thr is instantiated from the jthread class.
  • The statement (request) to stop the thread as soon as possible is placed before the join() statement. In this case, the calling thread is to stop the called thread from continuing to execute.

Is Stop Possible?

In some situations, it is not possible to stop a thread. However, the programmer cannot know if a thread can be stopped or not. In this case, the programmer has to inquire. The stop_source has the member function,

    bool stop_possible() const

If the return value is true, then it is possible to stop the thread before its natural end. If the return value is false, it is impossible to stop the thread before its natural end. jthread has a method that can return the stop_source object.

So, it may be better to ask if a thread can be stopped before stopping the thread. The following program illustrates this:

    #include <iostream>

    #include <thread>

    using namespace std;


    void fn() {

        cout <<"first code segment of thread" <<endl;

        cout <<"second code segment of thread" <<endl;

    }


    int main()

    {

        jthread thr(fn);

        stop_source ss = thr.get_stop_source();

        if (ss.stop_possible())

            thr.request_stop();

        else

            cout <<"Thread could be stopped!" <<end;

        thr.join();


        return 0;

    }

The stopping code segment has been placed before the join statement.

Has Stop Request been made?

If it is possible to stop a thread, that still does not guarantee that a request_stop() statement will succeed in stopping the thread before its natural end. If the thread has not stopped before its natural end as hoped for, then the programmer may want to know if the thread had been asked to stop with the request_stop() statement.

The stop_token object has the member function,

    bool stop_requested()

This function returns true if a stop request has been made and false otherwise. The jthread object can return a stop_token object, with its member function,

    stop_token get_stop_token() const

The following main() function code illustrates how to know if a request_stop has been issued:

    int main()

    {

        jthread thr(fn);

        stop_source ss = thr.get_stop_source();

        if (ss.stop_possible())

            thr.request_stop();

        else

            cout <<"Thread could be stopped!" <<end;


        stop_token st = thr.get_stop_token();

        if (st.stop_requested())

            cout <<"Still waiting for thrread to stop." <<endl;

        else

            thr.request_stop();


        thr.join();


        return 0;

    }

All the stopping code is before the join statement. Do not confuse between request_stop() and stop_requested() functions.

Conclusion

A thread can be killed responsibly with C++20 and higher. This means stopping the thread with the resources of the thread, freed. The thread library has the stop_token, stop_source, stop_callback, and jthread classes for killing a thread responsibly. To use the stop_token, stop_source, and stop_callback instantiated objects, create the thread with the jthread class. The jthread class is in the thread library, which has to be included in the C++ program.

The jthread class has member functions to return the stop_token and stop_source objects. The jthread class itself has the member function, request_stop(), to stop a thread. This request is likely to be granted, but there is no guarantee that it will be granted. If the request is granted, then the thread stops as soon as possible, without reaching its natural end, everything being equal.

The stop_source object can be used to know if stopping a thread is possible. The stop_token object can be used to know if a request_stop() has been issued. Once a stop request has been made, it cannot be withdrawn (a subsequent stop request has no effect).

About the author

Chrysanthus Forcha

Discoverer of mathematics Integration from First Principles and related series. Master’s Degree in Technical Education, specializing in Electronics and Computer Software. BSc Electronics. I also have knowledge and experience at the Master’s level in Computing and Telecommunications. Out of 20,000 writers, I was the 37th best writer at devarticles.com. I have been working in these fields for more than 10 years.