• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Błąd C2327 i C2065

Object Storage Arubacloud
0 głosów
95 wizyt
pytanie zadane 26 września 2022 w C i C++ przez RufinB Obywatel (1,830 p.)

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

 

1 odpowiedź

+1 głos
odpowiedź 27 września 2022 przez j23 Mędrzec (194,920 p.)
wybrane 28 września 2022 przez RufinB
 
Najlepsza

Odwołujesz się do tablicy hazard_pointers_stack::tab z wnętrza konstruktora hazard_pointers_stack::hp_owner. To nie Java. Jak chcesz mieć dostęp do tab z wnętrza hp_owner, musisz przekazać wskaźnik w parametrze konstruktora.

komentarz 27 września 2022 przez RufinB Obywatel (1,830 p.)

poprawiłem ale teraz ten fragment kodu powoduje błąd. Przecież klasa rezydent po to jest tworzona aby definiować jej obiekty wewnątrz klasy zewnętrznej

std::atomic<void*>& get_owner_hazard_pointer() {
		thread_local static hp_owner(tab) temp;
		return temp.get_pointer();
	}

 

komentarz 27 września 2022 przez j23 Mędrzec (194,920 p.)

Po:

  • pierwsze: czytaj treść błędów, jakie kompilator wyrzuca.
  • drugie: przytaczaj ich treść na forum i miejsce w kodzie, bo samo "powoduje błąd" niewiele mówi.
  • trzecie:  thread_local static hp_owner temp(tab);

IMO to przekazanie tab z obiektu niestatycznego do statycznego jest ryzykowne. Pewny jesteś tej konstrukcji?

komentarz 27 września 2022 przez RufinB Obywatel (1,830 p.)
fragment ten powoduje błędy:

Błąd    C3861    "temp": identyfikatora nie odnaleziono    
Błąd    C2065    "temp": niezadeklarowany identyfikator  

W tej tablicy znajduje się 100 wskaźników ryzyka w formie tablicy która jest przekazywane do konstruktora tworzącego jedną klasę hp_owner. Klasa ta powinna być własnością indywidualną każdego wątku i każda taka klasa musi mieć ten sam egzemplarz tej tablicy
komentarz 28 września 2022 przez j23 Mędrzec (194,920 p.)

i każda taka klasa musi mieć ten sam egzemplarz tej tablicy

To dlaczego ta tablica nie jest statyczna, a jest zwykłym polem klasy hazard_pointers_stack?

komentarz 28 września 2022 przez RufinB Obywatel (1,830 p.)

Chcę żeby było tak że każdy obiekt klasy hazard_pointers_stack miał własną tablicę z hazard_pointers a każdy obiekt hp_owner miał dostęp do tej samej tablicy ale miał indywidualny wskaźnik hp dla każdego wątku

tak wygląda poprawiony kod 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& _data) :
			data(std::make_shared<T>(_data)), next(nullptr) {
		}
	};	
	static constexpr unsigned size = 100;
	struct hazard_pointers {
		std::atomic<std::thread::id> id;
		std::atomic<void*> data;
	};
	static hazard_pointers tab[size];
	struct hp_owner {
	
		hazard_pointers* hp;
	
		hp_owner(hazard_pointers* temp) :hp(nullptr) {
			for (int i = 0; i < size; i++) {
				std::thread::id empty_id;
				if (temp[i].id.compare_exchange_strong(empty_id, std::this_thread::get_id()))
				{
					hp=temp + 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(tab) 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);
	}
};

linijkę powodującą błąd oznaczyłem znakami komentarza 

komentarz 28 września 2022 przez RufinB Obywatel (1,830 p.)
już działa zrobiłem literówkę i poprawiłem funkcje deleter na lambdę

Dzięki za podpowiedzi

Nie znaleziono podobnych pytań

92,572 zapytań

141,422 odpowiedzi

319,644 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...