Skip to content

Latest commit

 

History

History
223 lines (203 loc) · 11.5 KB

README.md

File metadata and controls

223 lines (203 loc) · 11.5 KB

How to use std::thread

Do you want a portable standard way to start and stop threads? Of course you do! Enter std::thread

Let's start simple and kick off a thread that uses a local function.

Note the use of std::ref here. This creates a reference_wrapper< T > around the object provided and allows it to be passed to our function.

Note also the use of join(). This will cause the current thread to block and wait for the child thread to complete e.g.:

struct thread_context { std::string output; };
static void thread_fn (const thread_context& context) {
    for (int i = 0; i < 1000; i++) {
        std::cout << context.output;
    }
}

int main (void) {
    auto c1 = thread_context{std::string("A")};
    auto a = std::thread(thread_fn, std::ref(c1));
    a.join();
}

Simpler yet is to use a lamda function:

    auto lambda = ([](void) {
        for (int i = 0; i < 1000; i++) { std::cout << "A"; }
    });
    auto a = std::thread(lambda);
    a.join();
}

Another approach is to wrap the thread in a class. The class will destroy the thread in its destructor, but will also block with join until the thread has finished executing:

    class MyThread {
    public:
        ~MyThread () {
            std::cout << to_string() << " destructor" << std::endl;
            //
            // Wait for our thread to finish
            //
            if (my_thread.joinable()) {
                my_thread.join();
            }
        }
        MyThread (const std::string& data, const int count) :
          data(data), count(count) {
            //
            // Start our thread.
            //
            my_thread = std::thread(&MyThread::run, this);
        }
        void run() { while (count--) { std::cout << data; } }
    private:
        std::thread my_thread;
        int count;
    };

    int main (void) {
        MyThread thread1("A", 1000);
    }

Of final note, you can print the unique identifier for the thread as such (this can be useful in debugging):

    std::stringstream ss;
    ss << std::this_thread::get_id();
    std::cout << "MyThread(" + ss.str() + ")" << std::endl;

Here is a full example:

#include <iostream>
#include <sstream>
#include <string>
#include <thread>

static const auto thread_loop_count = 1000;

////////////////////////////////////////////////////////////////////////////
// Here we start a thread with a class wrapper. We will not complete
// destruction of this class until our thread is finished.
////////////////////////////////////////////////////////////////////////////
class MyThread
{
public:
  ~MyThread()
  {
    std::cout << to_string() << " destructor" << std::endl;
    //
    // Wait for our thread to finish
    //
    if (my_thread.joinable()) {
      my_thread.join();
    }
  }
  MyThread(const std::string &data, const int count) : data(data), count(count)
  {
    //
    // Start our thread.
    //
    my_thread = std::thread(&MyThread::run, this);
    std::cout << to_string() << " constructor" << std::endl;
  }
  std::string to_string(void) const
  {
    std::stringstream ss;
    ss << std::this_thread::get_id();
    return "MyThread(" + ss.str() + ")";
  }
  void run()
  {
    while (count--) {
      std::cout << data;
    }
  }

private:
  std::thread my_thread;
  std::string data;
  int         count;
};

static void thread_with_class_example()
{
  // Start 2 threads with class wrappers
  MyThread thread1("A", thread_loop_count);
  MyThread thread2("B", thread_loop_count);
  // Wait for threads to finish
}

////////////////////////////////////////////////////////////////////////////
// Here we start threads with a local function that is passed some context
////////////////////////////////////////////////////////////////////////////
struct thread_context {
  std::string output;
};
static void thread_fn(const thread_context &context)
{
  for (int i = 0; i < thread_loop_count; i++) {
    std::cout << context.output;
  }
}

static void thread_with_local_function_and_cotext()
{
  // Start 2 threads implemented as function calls
  auto c1 = thread_context {std::string("A")};
  auto c2 = thread_context {std::string("B")};
  auto a  = std::thread(thread_fn, std::ref(c1));
  auto b  = std::thread(thread_fn, std::ref(c2));
  a.join();
  b.join();
  // Wait for threads to finish
}

////////////////////////////////////////////////////////////////////////////
// Here we start threads with lambdas
////////////////////////////////////////////////////////////////////////////
static void thread_with_lambda()
{
  // Start 2 threads implemented as lambdas
  auto l1 = ([](void) {
    for (int i = 0; i < thread_loop_count; i++) {
      std::cout << "A";
    }
  });
  auto l2 = ([](void) {
    for (int i = 0; i < thread_loop_count; i++) {
      std::cout << "B";
    }
  });
  auto a  = std::thread(l1);
  auto b  = std::thread(l2);
  a.join();
  b.join();
  // Wait for threads to finish
}

int main()
{
  thread_with_class_example();
  thread_with_local_function_and_cotext();
  thread_with_lambda();

  // End
  return 0;
}

To build:

cd std_thread
rm -f *.o example
clang -std=c++2a -Werror -g -O3 -fstack-protector-all -ggdb3 -Wall -c -o main.o main.cpp
clang  main.o -lstdc++  -lpthread -o example
./example

Expected output:

�[31;1;4mStart 2 threads with class wrappers�[0m
MyThread(139886966064128) constructor
MyThread(139886966064128) constructor

�[31;1;4mWait for threads to finish�[0m
MyThread(139886966064128) destructor
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBABBBABBBABABBBABBBABBBBABBBABBBABABBAAABABBABAAABABABBABBABABBBABBBABABAABABABBBABAABABBABAAABABABBBABABABBBBABAABABABBBBABBABABABBBBABAABABBABABABBBABAABABBBABAABAAABABABAABABBABAABABAABAABABABBBABAABABAABABABBBABBBABABABBBABAABABABABBABABBBBABABABAABAABABABABABABBBABABABBBABBABAABABABBBABABABABABBBABABABBABABABAABABABBBABABBBBABAABABABBABAAABABBABBBABABABABABBABABBBABABABBABBABBBBABABABABABBABABBBABABABABABABABBBABBBABAABAAABAABABABAABBABAABBBABBABAABABBBABAABABBBABAABABABABBABAABAABABBABABABBABBABABABABABBBABABABABABBBABAABABABBBABABBBABBBABBABABABABABBBABABBABABABBBABABABBBBABAABABABABABBABABABABABBABABABBABABBBBABABABAABABBBABABABABABABABABBABABABBBABABABABABABBBABABABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMyThread(139886966064128) destructor

�[31;1;4mStart 2 threads implemented as function calls�[0m
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABBAAAAABABABAAAABBABABAAABAAABABBABAAABAAABAAAABAAAABAAAABABBBABBBAABAAABABBABBBABAABABBBABBBBABBBBBABAABAAABAAAABABBBABBBBABBBBABBBABBBABBBABABABABABBBABABABBBABAABAABABBABABBABBBBABBBAABAAABAAABABAABABABAABAAABABBABBBABBBABABBABAABABBBABBBABABAABAAABABAABAAAABAAAAABABBABABABBABAABAAABAAABABBBABBABAABABBBABABABBBABBABAABABBABAABABBBABBABAAABABBBABBBBBABBBABABABBAABAAABABBABAABABAABABBABBBABBABBBABABABABAAABAABABBBABBBABABABBABABABBBABABAABABABAABABABAAABAABABABAABAABAABBABBBABAAABAAAABAAAABABABABAAABAAABAABABAABAABABBABAABABBBABAABAAABABBABABBBABAABABABAAABAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
�[31;1;4mWait for threads to finish�[0m

�[31;1;4mStart 2 threads implemented as lambdas�[0m
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABBBABBABABBBABABABABBABABABAAAAABABBAABAAABABBABABAAABAABABABABBBABABABABABABABBABAAAABAABABBABAABAABAAAABAAAABABBABAABABBBABABABABABABAABAABABBBABBBBABBABAABABAAABAABABBABABAABABBABAAABABAABABAABABBABABBABAAABAAABABBABAABABBBABAABABAABABAABABBBBABBABAABABBABABBBABBBABAABABBBABBBABAAABAAABAAABABBBABAABABABAABABBABAAABABBABAABABBABAAABAABAAABABABAABABBABAABABABAABABBABAAABABBABBABABBABAABABBBABBABAABABBABBABABABABBABABABBBABBABAABABABABBABAABABBBABAAABABBBABBABAABABBBABBABABBABAABABAABABBABAABABAABABBABAABABBBABAABABABAABABBBABABBABAAABABABAAABABABABBABAAABAABBABABABBABAAABABBBABABABBABBABAABABBBABAAABAABABBBBABBBABAABABBABAAABAAABABBABAAABAAABABAABABBBABABABBBABBBABAABABBABABAABABAAABAAABABBBABAABABBBABABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
�[31;1;4mWait for threads to finish�[0m

# End