Clicky

How to run threads

Frequently people struggle with simple things when writing multithreaded applications, here I will lay out some simple rules and provide a C++ pattern that can be followed to make multithreading a breeze. This will be focused on C++, but most of the ideas apply to other languages as well.

Example code:

#include <thread>
#include <memory>
#include <iostream>

class ThreadedClassPattern
{
public:
    static std::shared_ptr<ThreadedClassPattern> create()
    {
        std::shared_ptr<ThreadedClassPattern> ret(
            new ThreadedClassPattern());
        ret->_thread.reset(new std::thread(
            &ThreadedClassPattern::classThread, ret.get()));
        return ret;
    }

    ~ThreadedClassPattern()
    {
        _threadRunning = false;
        _thread->join();
    }
protected:
private:
    ThreadedClassPattern()
        : _threadRunning(true)
    {
    }

    void classThread()
    {
        while (_threadRunning == true)
        {
            // process data, but any blocking
            // call should never block indefinitely
            std::this_thread::sleep_for(
                std::chrono::milliseconds(1));
        }
    }

    bool _threadRunning;
    std::unique_ptr<std::thread> _thread;
};

int main(int argc, char* argv[])
{
    try
    {
        std::shared_ptr<ThreadedClassPattern> classInstance =
            ThreadedClassPattern::create();
        // do whatever you need to do...
    }
    catch (const std::exception& ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
    }
    return 0;
}

Reachable exit conditions:

The first rule of spawning a thread is that it must have an easily reachable exit condition, even in error cases. This means that threads can not block for potentially infinite amounts of time. The classic case is spawning a thread to read from a blocking socket, then when the application exits (either normally, or due to an error) the thread remains blocked.

So all blocking calls must have a timeout, or better yet do not use blocking calls. It is fine to block for some small amount of time just to prevent wasting cpu cycles, or for other reasons like synchronization, but making a blocking call that can block forever in a thread is an error! The same goes for synchronization points like semaphores, and mutexes. It is fine (and in fact necessary) to use these things, but reasonable timeouts must also be used and error cases handled correctly.

Killing a thread, or forcing it to just stop running prematurely is a bug, a thread must always exit voluntarily so that it can correctly release all resources.

In the above example, the code does a sleep in the thread, but only for 1 millisecond, so even if an error occurs anywhere, the thread will still exit in the worst case around 1 millisecond after the exception handling code causes the destructor to be invoked.

Isn’t it bad to call join in destructors?

Some people will say that calling join in destructors is bad, because when the object is destroyed due to an exception you must then wait for the thread to stop before you can actually process the exception. However I argue that if you do not violate the first rule, then this is not an issue. If your thread can always exit in a timely fashion, then it actually simplifies things, and allows you to use your destructors to fully destruct your objects.

Use the factory pattern:

During object creation in C++, if an exception occurs before the object is fully constructed (i.e. in the constructor) then the destructor will not be invoked. If a thread has been created in the class constructor, and then an exception occurs later on in the constructor, you must play some games to cause the thread to stop running, I have seen the following:

  • Do nothing, just let the thread run, it will probably be ok? right?
  • Catch all exceptions in the constructor and then stop/join the thread, then re-throw the exception… This gets messy pretty fast.
  • Use the factory pattern, create the object, then if no exception occurs, start the thread. So easy, and clean, everyone should do it.

The above code shows how easy it is to use the factory pattern, just call the static create() function, and when/if the object is fully constructed, the thread will be started, subsequently when the object is destroyed, the thread will be stopped in the destructor.

Summary:

Synchronization, race conditions, etc… are not covered here, there are many other places on the webs that you can read about these things, I just wanted to give a quick demo of how to create a threaded class in C++ that resolves some frequently overlooked errors. It seems like there is a new question every week on stack overflow about “how do I terminate my thread which is blocked” or some such non-sense… So this is how you do it.

Posted in Programming
2 comments on “How to run threads
  1. AldurDisciple says:

    Hi, thank you for this article. I realize this might be a bit late to ask a question, but I was wondering: you do not use a synchronization scheme to access the boolean ‘_threadRunning’, is this on purpose ?

    • chrisd says:

      The only synchronization needed for _threadRunning is the join() in the destructor. Assuming you follow my advice and do not block in the thread excessively, then everything works perfectly, and your users are happy.

Leave a Reply

Your email address will not be published. Required fields are marked *

*