#include <array>
#include <atomic>
#include <iostream>
#include <stdexcept>
#include <thread>
struct InjectedFailure {};
void increment(std::atomic<int>& count,bool inject_failure=false) {
    std::array<std::thread,4> workers;
    struct JoinAll {
        std::array<std::thread,4>& threads;
        ~JoinAll() {for(auto& t:threads) if(t.joinable()) t.join();}
    } join_all{workers};
    std::size_t started=0;
    for(auto& t:workers) {
        if(inject_failure && started==1) throw InjectedFailure{};
        t=std::thread([&]{
            for(int i=0;i<10000;++i) count.fetch_add(1,std::memory_order_relaxed);
        });
        ++started;
    }
    for(auto& t:workers) t.join();
}
int main() {
    std::atomic<int> count{0}; increment(count);
    const int result=count.load(std::memory_order_relaxed);
    if(result!=40000) throw std::runtime_error("count");
    std::atomic<int> partial{0}; bool caught=false;
    // Test-only failure before thread two; the first thread must finish before catch.
    try {increment(partial,true);} catch(const InjectedFailure&) {caught=true;}
    if(!caught || partial.load(std::memory_order_relaxed)!=10000)
        throw std::runtime_error("join on creation failure");
    std::cout<<"count="<<result<<'\n';
}
