#include <array>
#include <atomic>
#include <iostream>
#include <stdexcept>
#include <thread>
struct InjectedFailure {};
int publish(int& payload,bool inject_failure=false) {
    int observed=0; std::atomic<bool> ready{false};
    std::array<std::thread,2> workers;
    struct JoinAll {
        std::array<std::thread,2>& threads;
        ~JoinAll() {for(auto& t:threads) if(t.joinable()) t.join();}
    } join_all{workers};
    workers[0]=std::thread([&]{payload=42; ready.store(true,std::memory_order_release);});
    // Model consumer construction failure while retaining and joining the producer.
    if(inject_failure) throw InjectedFailure{};
    workers[1]=std::thread([&]{
        while(!ready.load(std::memory_order_acquire)) std::this_thread::yield();
        observed=payload;
    });
    for(auto& worker:workers) worker.join();
    return observed;
}
int main() {
    for(int trial=0;trial<100;++trial) {
        int payload=0;
        if(publish(payload)!=42) throw std::runtime_error("publication");
    }
    int partial_payload=0; bool caught=false;
    try {
        const int unexpected=publish(partial_payload,true);
        std::cout<<"unexpected publication result="<<unexpected<<'\n';
        return 1;
    } catch(const InjectedFailure&) {caught=true;}
    if(!caught || partial_payload!=42) throw std::runtime_error("join on creation failure");
    std::cout<<"published=42 trials=100\n";
}
