std::thread Class

  • Implemented using RAII

    • Similar to std::unique_ptr, std::fstream, etc
    • The constructor acquires a resource
    • The destructor releases the resource
  • An std::thread object has ownership of an execution thread

    • Only one object can be bound to an execution thread at a time

std::thread and Move Semantics

  • Move-only class

    • std::thread objects cannot be copied
  • Move operations

    • Transfer ownership of the execution thread
    • The moved-from object is no longer associated with an execution thread

Passing a std::thread Object

  • Must use pass by move
// Function taking a thread object as argument
void func(std::thread thr);

// Pass a named object
// Use std::move() to cast it to rvalue
std::thread thr(...);
func(std::move(thr));

// Pass a temporary object
func(std::thread(...));

  • Moving a thread

#include <iostream>
#include <thread>

using namespace std::literals;

void hello() {
  std::this_thread::sleep_for(2s);
  std::cout << "hello, thread!\n";
}

// caller must provide an rvalue
void func(std::thread &&thr) {
  std::cout << "Recieved thread with ID " << thr.get_id() << std::endl;

  // the function argument now "owns" the system thread
  // it is responsible for calling join()
  thr.join();
}

int main() {
  std::cout << "Starting thread...\n";
  // std::thread is a move only object
  std::thread thr(hello);

  func(std::move(thr));
}

Returning a std::thread Object

  • The compiler will automatically move it for us
// Function returning a std::thread object
std::thread func() {
  // Return a local variable
  std::thread thr(...);
  return thr;

  // Return a temporary object
  return std::thread(...);
}
// The caller must use .join();

Threads and Exceptions

  • Each thread has its own execution stack

  • The stack is "unwound" when the thread throws an exception

    • The destructors for all objects in scope are called
    • The program moves up the thread's stack until it finds a suitable handler
    • If no handler is found, the program is terminated
  • Other threads in the program cannot catch the exception

    • Including the parent thread and the main thread
  • Exceptions can only be handled in the thread where they occur

    • Use a try/catch block in the normal way

#include <exception>
#include <iostream>
#include <thread>

void hello() {
  try {
    throw std::exception();
  } catch (std::exception &e) {
    std::cout << "exception caught: " << e.what() << '\n';
  }
  std::cout << "Hello, Thread!\n";
}

int main() {
  std::thread thr(hello);
  thr.join();
  std::cout << "Finished\n";
}