linijki w konstruktorze klasy hp_owner powodują dwa błędy zawarte w tytule, nie wiem czemu. Fragment powodujący błąd zamieszczam poniżej a w pozostałych dwóch likach zamieszczam cały kod
static constexpr unsigned size = 100;
struct hazard_pointers {
std::atomic<std::thread::id> id;
std::atomic<void*> data;
};
hazard_pointers tab[size];
struct hp_owner {
hazard_pointers* hp;
hp_owner() :hp(nullptr) {
for (int i = 0; i < size; i++) {
std::thread::id empty_id;
if (tab[i].id.compare_exchange_strong(empty_id, std::this_thread::get_id()))
{
hp=tab + i;
break;
}
}
if (!hp) {
throw std::runtime_error("nie ma wolnych wskaznikow ryzyka");
}
}
~hp_owner() {
hp->data.store(nullptr);
hp->id.store(std::thread::id());
}
std::atomic<void*>& get_pointer() {
return hp->data;
}
};
plik hazard_pointer_stack.h
#pragma once
#include <atomic>
#include <stdexcept>
#include <memory>
#include <thread>
#include <functional>
template <typename T>
class hazard_pointers_stack {
private:
struct node {
std::shared_ptr<T> data;
node* next;
node(const T&);
};
static constexpr unsigned size = 100;
struct hazard_pointers {
std::atomic<std::thread::id> id;
std::atomic<void*> data;
};
hazard_pointers tab[size];
struct hp_owner {
hazard_pointers* hp;
hp_owner() :hp(nullptr) {
for (int i = 0; i < size; i++) {
std::thread::id empty_id;
if (tab[i].id.compare_exchange_strong(empty_id, std::this_thread::get_id()))
{
hp=tab + i;
break;
}
}
if (!hp) {
throw std::runtime_error("nie ma wolnych wskaznikow ryzyka");
}
}
~hp_owner() {
hp->data.store(nullptr);
hp->id.store(std::thread::id());
}
std::atomic<void*>& get_pointer() {
return hp->data;
}
};
template <typename T>
void deleter_func(void* ptr) {
delete reinterpret_cast<T*>(ptr);
}
struct data_to_reclaim {
void* data;
std::function<void(void*)> deleter;
data_to_reclaim* next;
template <typename T>
data_to_reclaim(T* p) :
data(p),
deleter(&deleter_func<T>),
next(nullptr) {
}
~data_to_reclaim() {
deleter(data);
}
};
std::atomic<node*> head;
std::atomic<data_to_reclaim*> node_to_reclaim;
std::atomic<void*>& get_owner_hazard_pointer() {
thread_local static hp_owner temp;
return temp.get_pointer();
}
bool check_hazard_list(void* p) {
for (int i = 0; i < size; i++) {
if (tab[i].data.load() == p)
return true;
}
return false;
}
template <typename T>
void add_to_reclaim_list(data_to_reclaim* p) {
p->next = node_to_reclaim.load();
while (!node_to_reclaim.compare_exchange_weak(p->next,p));
}
void reclaim_later(node* temp) {
add_to_reclaim_list<node>(new data_to_reclaim(temp));
}
void try_delete_node_to_reclaim() {
data_to_reclaim* curent = node_to_reclaim.exchange(nullptr);
while (curent) {
data_to_reclaim* next = curent;
if (check_hazard_list(curent->data))
delete curent;
else
add_to_reclaim_list<node>(curent);
curent = next;
}
}
public:
std::shared_ptr<T> pop() {
node* old_head = head.load();
std::atomic<void*>& hp = get_owner_hazard_pointer();
do {
node* temp;
do {
temp = old_head;
hp.store(old_head);
old_head = head.load();
} while (temp != old_head);
} while (old_head&&!head.compare_exchange_strong(old_head, old_head->next));
hp.store(nullptr);
std::shared_ptr<T> res;
if (old_head){
res.swap(old_head->data);
if (check_hazard_list(old_head)) {
reclaim_later(old_head);
}
else {
delete old_head;
}
}
try_delete_node_to_reclaim();
return res;
}
void push(const T& data) {
node* temp = new node(data);
temp->next = head.load();
while (!head.compare_exchange_weak(temp->next, temp));
}
hazard_pointers_stack() :
node_to_reclaim(nullptr) {
head.store(nullptr);
}
};
template <typename T>
hazard_pointers_stack<T>::node::node(const T& _data) :
data(std::make_shared<T>(_data)), next(nullptr) {
}
plik main.cpp
#include <iostream>
#include <thread>
//#include "lock_free_stack.h"
#include "hazard_pointers_stack.h"
using namespace std;
hazard_pointers_stack<int> temp;
void add_function() {
for (int i = 0; i < 500000; i++) {
temp.push(i);
}
}
void pop_function() {
for (int i = 0; i < 500000; i++) {
temp.pop();
}
}
int main()
{
thread t1(add_function);
thread t2(add_function);
t1.join();
t2.join();
thread t3(pop_function);
thread t4(pop_function);
t3.join();
t4.join();
shared_ptr<int> t;
if (!temp.pop())
cout << "udalo_sie" << endl;
else
cout << "nie udalo sie" << endl;
}