#include<algorithm>
#include<atomic>
#include<exception>
#include<iostream>
#include<memory>
#include<stdexcept>
#include<thread>
#include<utility>
#include<vector>
using namespace std;
class thr_stack
{
struct Node
{
int data;
std::shared_ptr<Node> next;
Node(const std::shared_ptr<Node> &next_,int data_)
:data{data_},next{next_}{}
};
std::shared_ptr<Node> begin_;
public:
void emplace(int data)
{
begin_=std::make_shared<Node>(begin_,data);
}
int pop()
{
std::shared_ptr<Node> node{std::atomic_load(&begin_)};
while(node&&!std::atomic_compare_exchange_weak_explicit(&begin_,&node,node->next
,std::memory_order_seq_cst
,std::memory_order_seq_cst))
;
if(node)
return node->data;
throw logic_error{"nullptr"};
}
~thr_stack()
{
while(begin_)
{
std::shared_ptr<Node> p{std::move(begin_->next)};
begin_.reset();
begin_=std::move(p);
}
}
};
constexpr int max_num{1000000};
thr_stack stack;
vector<atomic<int>> vec(max_num);
void read_test(int);
int main()
{
for(int i{0};i!=max_num;++i)
stack.emplace(i);
#if 1 //the problem here
const unsigned int thread_count{std::thread::hardware_concurrency()};
vector<thread> thr;
for(unsigned int i{0};i!=thread_count;++i)
thr.emplace_back(read_test,max_num/thread_count);
for(unsigned int i{0};i!=thread_count;++i)
thr[i].join();
#else
read_test(max_num);
#endif
if(all_of(begin(vec),end(vec),[](auto &val){return val==1;}))
cout<<"succeed"<<endl;
}
void read_test(int count)
{
try
{
for(int i{0};i!=count;++i)
++vec.at(stack.pop());
}catch(const exception &e)
{
cerr<<e.what()<<endl; //cannot catch anything
}
}
I2luY2x1ZGU8YWxnb3JpdGhtPgojaW5jbHVkZTxhdG9taWM+CiNpbmNsdWRlPGV4Y2VwdGlvbj4KI2luY2x1ZGU8aW9zdHJlYW0+CiNpbmNsdWRlPG1lbW9yeT4KI2luY2x1ZGU8c3RkZXhjZXB0PgojaW5jbHVkZTx0aHJlYWQ+CiNpbmNsdWRlPHV0aWxpdHk+CiNpbmNsdWRlPHZlY3Rvcj4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNsYXNzIHRocl9zdGFjawp7CglzdHJ1Y3QgTm9kZQoJewoJCWludCBkYXRhOwoJCXN0ZDo6c2hhcmVkX3B0cjxOb2RlPiBuZXh0OwoJCU5vZGUoY29uc3Qgc3RkOjpzaGFyZWRfcHRyPE5vZGU+ICZuZXh0XyxpbnQgZGF0YV8pCgkJCTpkYXRhe2RhdGFffSxuZXh0e25leHRffXt9Cgl9OwoJc3RkOjpzaGFyZWRfcHRyPE5vZGU+IGJlZ2luXzsKcHVibGljOgoJdm9pZCBlbXBsYWNlKGludCBkYXRhKQoJewoJCWJlZ2luXz1zdGQ6Om1ha2Vfc2hhcmVkPE5vZGU+KGJlZ2luXyxkYXRhKTsKCX0KCWludCBwb3AoKQoJewoJCXN0ZDo6c2hhcmVkX3B0cjxOb2RlPiBub2Rle3N0ZDo6YXRvbWljX2xvYWQoJmJlZ2luXyl9OwoJCXdoaWxlKG5vZGUmJiFzdGQ6OmF0b21pY19jb21wYXJlX2V4Y2hhbmdlX3dlYWtfZXhwbGljaXQoJmJlZ2luXywmbm9kZSxub2RlLT5uZXh0CgkJCSAgLHN0ZDo6bWVtb3J5X29yZGVyX3NlcV9jc3QKCQkJICAsc3RkOjptZW1vcnlfb3JkZXJfc2VxX2NzdCkpCgkJCTsKCQlpZihub2RlKQoJCQlyZXR1cm4gbm9kZS0+ZGF0YTsKCQl0aHJvdyBsb2dpY19lcnJvcnsibnVsbHB0ciJ9OwoJfQoJfnRocl9zdGFjaygpCgl7CgkJd2hpbGUoYmVnaW5fKQoJCXsKCQkJc3RkOjpzaGFyZWRfcHRyPE5vZGU+IHB7c3RkOjptb3ZlKGJlZ2luXy0+bmV4dCl9OwoJCQliZWdpbl8ucmVzZXQoKTsKCQkJYmVnaW5fPXN0ZDo6bW92ZShwKTsKCQl9Cgl9Cn07Cgpjb25zdGV4cHIgaW50IG1heF9udW17MTAwMDAwMH07CnRocl9zdGFjayBzdGFjazsKdmVjdG9yPGF0b21pYzxpbnQ+PiB2ZWMobWF4X251bSk7Cgp2b2lkIHJlYWRfdGVzdChpbnQpOwoKaW50IG1haW4oKQp7Cglmb3IoaW50IGl7MH07aSE9bWF4X251bTsrK2kpCgkJc3RhY2suZW1wbGFjZShpKTsKI2lmIDEJLy90aGUgcHJvYmxlbSBoZXJlCgljb25zdCB1bnNpZ25lZCBpbnQgdGhyZWFkX2NvdW50e3N0ZDo6dGhyZWFkOjpoYXJkd2FyZV9jb25jdXJyZW5jeSgpfTsKCXZlY3Rvcjx0aHJlYWQ+IHRocjsKCWZvcih1bnNpZ25lZCBpbnQgaXswfTtpIT10aHJlYWRfY291bnQ7KytpKQoJCXRoci5lbXBsYWNlX2JhY2socmVhZF90ZXN0LG1heF9udW0vdGhyZWFkX2NvdW50KTsKCWZvcih1bnNpZ25lZCBpbnQgaXswfTtpIT10aHJlYWRfY291bnQ7KytpKQoJCXRocltpXS5qb2luKCk7CiNlbHNlCglyZWFkX3Rlc3QobWF4X251bSk7CiNlbmRpZgoJaWYoYWxsX29mKGJlZ2luKHZlYyksZW5kKHZlYyksW10oYXV0byAmdmFsKXtyZXR1cm4gdmFsPT0xO30pKQoJCWNvdXQ8PCJzdWNjZWVkIjw8ZW5kbDsKfQoKdm9pZCByZWFkX3Rlc3QoaW50IGNvdW50KQp7Cgl0cnkKCXsKCQlmb3IoaW50IGl7MH07aSE9Y291bnQ7KytpKQoJCQkrK3ZlYy5hdChzdGFjay5wb3AoKSk7Cgl9Y2F0Y2goY29uc3QgZXhjZXB0aW9uICZlKQoJewoJCWNlcnI8PGUud2hhdCgpPDxlbmRsOwkvL2Nhbm5vdCBjYXRjaCBhbnl0aGluZwoJfQp9