#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
	}
}