#include <array>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <thread>
struct InjectedFailure {};
void increment(int& count,bool inject_failure=false) {
    std::mutex mutex; 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) {
        // Teaching injection models failure before the second thread starts.
        if(inject_failure && started==1) throw InjectedFailure{};
        t=std::thread([&] {
            for(int i=0;i<1000;++i) {std::lock_guard lock(mutex); ++count;}
        });
        ++started;
    }
    for(auto& t:workers) t.join();
}
int main() {
    int count=0; increment(count);
    if(count!=4000) throw std::runtime_error("count");
    int partial=0; bool caught=false;
    try {increment(partial,true);} catch(const InjectedFailure&) {caught=true;}
    if(!caught || partial!=1000) throw std::runtime_error("join on creation failure");
    std::cout<<"count="<<count<<'\n';
}
