#include <vector>
#include <chrono>
#include <atomic>
#include <thread>
#include <cassert>
#include <iostream>
struct list {
struct node {
std::atomic<node*> next;
void start_operation() {
static std::atomic_int i;
++i;
int j = i;
using namespace std::literals;
std::this_thread::sleep_for((rand()%100/100.)*.01s);
std::cerr <<"doing it! i="<<j<<"\n";
assert(i == 1);
--i;
}
};
std::atomic<node*> tail{ nullptr };
void push(node* new_node) {
using namespace std::literals;
std::this_thread::sleep_for((rand()%100/100.)*.2s);
node* old_tail = tail.exchange(new_node);
std::this_thread::sleep_for((rand()%100/100.)*.2s);
if(old_tail == nullptr || old_tail->next.exchange(new_node) == old_tail) {
node* current = new_node;
while(true) {
current->start_operation();
std::this_thread::sleep_for((rand()%100/100.)*0.01s);
node* expected = nullptr;
if(current->next.compare_exchange_strong(expected, new_node)) return;
else current = expected;
}
}
}
};
int main() {
srand(1);
list l;
std::vector<std::thread> ts;
for (int i=0; i<10; ++i) {
ts.emplace_back([&l,i]() {
list::node n;
std::string s="push "+std::to_string(i)+"\n";
std::cerr << s;
l.push(&n);
s="finished "+std::to_string(i)+"\n";
std::cerr << s;
using namespace std::literals;
std::this_thread::sleep_for(1s);
});
}
for (auto& t : ts)
t.join();
std::cerr << "done\n";
}