#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_}{}
~Node()
{
while(next.use_count()==1)
{
std::shared_ptr<Node> p{std::move(next->next)};
next.reset();
next=std::move(p);
}
}
};
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"};
}
};
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+ICZuZXh0XyxpbnQgZGF0YV8pCgkJCTpkYXRhe2RhdGFffSxuZXh0e25leHRffXt9CgkJfk5vZGUoKQoJCXsKCQkJd2hpbGUobmV4dC51c2VfY291bnQoKT09MSkKCQkJewoJCQkJc3RkOjpzaGFyZWRfcHRyPE5vZGU+IHB7c3RkOjptb3ZlKG5leHQtPm5leHQpfTsKCQkJCW5leHQucmVzZXQoKTsKCQkJCW5leHQ9c3RkOjptb3ZlKHApOwoJCQl9CgkJfQoJfTsKCXN0ZDo6c2hhcmVkX3B0cjxOb2RlPiBiZWdpbl87CnB1YmxpYzoKCXZvaWQgZW1wbGFjZShpbnQgZGF0YSkKCXsKCQliZWdpbl89c3RkOjptYWtlX3NoYXJlZDxOb2RlPihiZWdpbl8sZGF0YSk7Cgl9CglpbnQgcG9wKCkKCXsKCQlzdGQ6OnNoYXJlZF9wdHI8Tm9kZT4gbm9kZXtzdGQ6OmF0b21pY19sb2FkKCZiZWdpbl8pfTsKCQl3aGlsZShub2RlJiYhc3RkOjphdG9taWNfY29tcGFyZV9leGNoYW5nZV93ZWFrX2V4cGxpY2l0KCZiZWdpbl8sJm5vZGUsbm9kZS0+bmV4dAoJCQkgICxzdGQ6Om1lbW9yeV9vcmRlcl9zZXFfY3N0CgkJCSAgLHN0ZDo6bWVtb3J5X29yZGVyX3NlcV9jc3QpKQoJCQk7CgkJaWYobm9kZSkKCQkJcmV0dXJuIG5vZGUtPmRhdGE7CgkJdGhyb3cgbG9naWNfZXJyb3J7Im51bGxwdHIifTsKCX0KfTsKCmNvbnN0ZXhwciBpbnQgbWF4X251bXsxMDAwMDAwfTsKdGhyX3N0YWNrIHN0YWNrOwp2ZWN0b3I8YXRvbWljPGludD4+IHZlYyhtYXhfbnVtKTsKCnZvaWQgcmVhZF90ZXN0KGludCk7CgppbnQgbWFpbigpCnsKCWZvcihpbnQgaXswfTtpIT1tYXhfbnVtOysraSkKCQlzdGFjay5lbXBsYWNlKGkpOwojaWYgMQkvL3RoZSBwcm9ibGVtIGhlcmUKCWNvbnN0IHVuc2lnbmVkIGludCB0aHJlYWRfY291bnR7c3RkOjp0aHJlYWQ6OmhhcmR3YXJlX2NvbmN1cnJlbmN5KCl9OwoJdmVjdG9yPHRocmVhZD4gdGhyOwoJZm9yKHVuc2lnbmVkIGludCBpezB9O2khPXRocmVhZF9jb3VudDsrK2kpCgkJdGhyLmVtcGxhY2VfYmFjayhyZWFkX3Rlc3QsbWF4X251bS90aHJlYWRfY291bnQpOwoJZm9yKHVuc2lnbmVkIGludCBpezB9O2khPXRocmVhZF9jb3VudDsrK2kpCgkJdGhyW2ldLmpvaW4oKTsKI2Vsc2UKCXJlYWRfdGVzdChtYXhfbnVtKTsKI2VuZGlmCglpZihhbGxfb2YoYmVnaW4odmVjKSxlbmQodmVjKSxbXShhdXRvICZ2YWwpe3JldHVybiB2YWw9PTE7fSkpCgkJY291dDw8InN1Y2NlZWQiPDxlbmRsOwp9Cgp2b2lkIHJlYWRfdGVzdChpbnQgY291bnQpCnsKCXRyeQoJewoJCWZvcihpbnQgaXswfTtpIT1jb3VudDsrK2kpCgkJCSsrdmVjLmF0KHN0YWNrLnBvcCgpKTsKCX1jYXRjaChjb25zdCBleGNlcHRpb24gJmUpCgl7CgkJY2Vycjw8ZS53aGF0KCk8PGVuZGw7CS8vY2Fubm90IGNhdGNoIGFueXRoaW5nCgl9Cn0=