Мой профессор C ++ дал нам упражнение, чтобы попрактиковаться в потокобезопасных структурах в C ++.
Это упражнение:
Создайте поточно-безопасный класс, который управляет рейтингом онлайн-игры: каждому игроку назначается псевдоним и счет. Создается метод для вставки игрока (или обновления его оценки, если он уже присутствует), в то время как другой метод создается для блокировки вызывающего его потока при ожидании изменения в рейтинге (слушатель).
Вот что я сделал:
class Classifica{
std::map<std::string,int> grad;
int nlistener=0;
std::mutex gm;
std::condition_variable didUpdate;
std::atomic<bool> variation = false;
public:
void insert(std::string nickname, int punteggio){ // every time i update i set the flag
int found = 0;
//take control
std::lock_guard<std::mutex> lg(gm);
// see if already present
std::map<std::string, int>::iterator it;
for (it = grad.begin();it != grad.end(); it++){
if (it->first == nickname)
found = 1;
}
if (found == 1){
if ( punteggio > grad[nickname])
grad[nickname] = punteggio;
} else {
grad.insert({nickname, punteggio});
}
// Notify update
variation = true;
didUpdate.notify_all();
}
void listener(){ //blocks thread
std::unique_lock<std::mutex> ug(gm);
nlistener++;
while (!variation){
didUpdate.wait(ug);
}
// ok variation happend i can unblock
nlistener--;
std::cout << "Variation happened" << std::endl;
if (nlistener == 0){
variation = false;
}
}
};
int main(){
Classifica myclass;
std::thread list1([&myclass] { myclass.listener(); });
std::thread ins1([&myclass] { myclass.insert("fede1",4); });
std::thread ins2([&myclass] { myclass.insert("fede2",4); });
std::thread list2([&myclass] { myclass.listener(); });
std::thread list3([&myclass] { myclass.listener(); });
std::thread ins3([&myclass] { myclass.insert("fede3",4); });
list2.join();
list3.join();
ins3.join();
list1.join();
ins1.join();
ins2.join();
return 0;
}
Проблема в том, что иногда программа не заканчивается, и я не могу понять, в чем проблема.
Может ли это быть в том, как потоки вызываются в основном?