Herb, thank you for your reply!
Regarding a relaxed stop=true on page 49: launch_workers() and join_workers() should normally both synchronize with the launched and joined workers, so shouldn't that prevent the worker threads from seeing the assignment too early or too late?
Regarding the relaxed exchange_explicit on page 54: If I'm not mistaken, the compiler or CPU can't move anything from the if-body to before the if-statement if that could lead to observable side effects when the if-condition evaluates to false. When the if-condition evaluates to true and any reader load-acquires a non-null instance pointer, the reader is guaranteed to see the fully constructed widget due to the store-release being sequenced after the new widget(). When the if-condition evaluates to false (after a thread saw a null instance), the thread load-acquires the instance pointer in a spin loop until it sees a non-null instance (which then again must be fully constructed). So, I still don't see why a relaxed exchange wouldn't be enough, what am I missing?