#include <algorithm>
#include <atomic>
#include <chrono>
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <thread>
#include <vector>
template <typename TaskType>
struct task_list {
struct node {
node(std::function<TaskType> task)
: task(task), next(nullptr) { }
std::function<void()> task;
std::atomic<node*> next;
};
std::atomic<node*> tail{ nullptr };
void push_task(std::function<TaskType> task) {
node* new_node = new node(task);
node* old_tail = tail.exchange(new_node, std::memory_order_relaxed);
if(old_tail == nullptr || old_tail->next.exchange(new_node, std::memory_order_consume) == old_tail) {
delete old_tail;
node* current = new_node;
for(;;) {
current->task();
node* expected = current->next.exchange(current, std::memory_order_release);
if(expected == nullptr) return;
else {
delete current;
current = expected;
}
}
}
}
~task_list() {
delete tail.load();
}
};
int main() {
task_list<void()> list;
std::vector<std::thread> threads;
std::string hello = "Hello, World!\n";
auto task = [&list, &hello] {
std::transform(std::begin(hello), std::end(hello), std::ostream_iterator<char>(std::cout), [](auto c) {
std::this_thread::yield();
std::this_thread::yield();
return c;
});
};
std::cout << "Ugly:\n";
for(int i = 0; i < 10; ++i) {
threads.emplace_back([&list, task] {
task();
});
}
for(auto& thread : threads)
if(thread.joinable()) thread.join();
threads.clear();
std::cout << "\nNice:\n";
for(int i = 0; i < 10; ++i) {
threads.emplace_back([&list, task] {
list.push_task(task);
});
}
for(auto& thread : threads)
if(thread.joinable()) thread.join();
}