Skip to content

NotACat1/ThreadRAII

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThreadRAII

C++ Build License

joining_thread is a lightweight RAII wrapper around std::thread designed to ensure a safe lifecycle for execution threads.

⚠️ The Problem with std::thread (Pre-C++20)

The standard std::thread has one unpleasant property: if a thread object goes out of scope while still joinable, and neither join() nor detach() has been called explicitly, the program immediately terminates via std::terminate(). This often leads to hard-to-debug crashes during exception handling or early function exits.

✨ The Solution

joining_thread implements the RAII (Resource Acquisition Is Initialization) idiom. It takes responsibility for thread completion:

  • Automatic join: The destructor checks the thread state and calls join() if needed
  • Safe move semantics: Correctly handles move assignment by joining the old thread before taking ownership of a new one
  • Interface compatibility: Uses variadic templates and perfect forwarding, allowing threads to be launched just as easily as with std::thread

🚀 Quick Start

#include "joining_thread.hpp"
#include <iostream>

void task(int seconds) {
    std::this_thread::sleep_for(std::chrono::seconds(seconds));
    std::cout << "Task complete!" << std::endl;
}

int main() {
    {
        joining_thread t(task, 2);
        // No need to call t.join()!
        // The thread will be safely joined when leaving this scope.
    }
    return 0;
}

🛠 Technical Details

Safe Assignment

Unlike naive implementations, joining_thread protects against std::terminate during move assignment:

joining_thread t1(worker, 1);
joining_thread t2(worker, 2);

t1 = std::move(t2); // t1 automatically joins its previous thread
                    // before taking ownership of t2's thread

Proxy Methods

The class provides access to the underlying thread via .get() and implements key parts of the std::thread interface (joinable(), join(), swap()), making it a drop-in replacement in most scenarios.


⚖️ Comparison with C++20 std::jthread

With the release of C++20, the standard introduced std::jthread. Our joining_thread conceptually mirrors its behavior but differs in several aspects:

Feature joining_thread (Custom) std::jthread (C++20)
Auto-join in destructor ✅ Yes ✅ Yes
Cooperative cancellation ❌ No (manual implementation required) ✅ Yes (via std::stop_token)
Compatibility C++11 and later C++20 only
Dependencies <thread> only <thread> + <stop_token>

Why use joining_thread if C++20 is available?

  1. Legacy projects — Your codebase is limited to C++11/14/17
  2. Minimalism — You need guaranteed joining but not the heavier stop_token mechanism
  3. Control — You want full control over wrapper behavior (e.g., logging in the destructor)

📜 License

This code is distributed under the MIT License. Use it for the benefit of robust and stable software.

About

A lightweight RAII wrapper for std::thread that ensures automatic joining on destruction. A C++11/14/17 compatible alternative to C++20's std::jthread.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages