Usuwanie treści z wektora.

0

Witam,
Mam wektor, który przechowuje obiekty, konkretnie gracze:
PlayerVector PlayersOnline;

Następnie mam funkcję w wątku, gdzie jest pętla, która "skanuje" ten wektor co kilka sekund i każdemu userowi zwiększa ping o jeden. Następnie poprzez ID porównuje, czy jest user i klient i klientowi wysyła ping. Jeśli klient odpowie, user ma wyzerowany ping. W ten teoretyczny sposób chcę zrobić timeout.

Problem w tym, że zatrzymałem się w momencie usuwania rekordów z wektora.

DWORD WINAPI Pingowanie(PVOID pvParam)
{
	PlayerVector tmpPlayersOnline = PlayersOnline; 
	ClientVector tmpClientsOnline = ClientsOnline;

	while(true)
	{
		Sleep(3000);
		Player* player = NULL;
		for(Piterator pit = PlayersOnline.begin(); pit != PlayersOnline.end(); pit++)
		{
			player = player->getPlayerById((*pit)->getPlayerId());
			if(player)
			{
				player->addPlayerPing();
				for(Citerator cit = ClientsOnline.begin(); cit != ClientsOnline.end(); cit++)
				{
					if((*pit)->getPlayerId() == (*cit).ID)
						(*cit).Send(4, "P");
				}
			}
		}

		for(Piterator pit = PlayersOnline.begin(); pit != PlayersOnline.end(); pit++)
		{
			if((*pit)->getPlayerPing() > 2)
			{
				tmpPlayersOnline.push_back(*pit);
				//std::cout << PlayersOnline.size() << std::endl;
			}
		}

		Player* tmpPlayer = NULL;
		for(Piterator it = tmpPlayersOnline.begin(); it != tmpPlayersOnline.end(); it++)
		{
			tmpPlayer = tmpPlayer->getPlayerById((*it)->getPlayerId());
			if(tmpPlayer)
			{
				if(strcmp((*it)->getPlayerName().c_str(), tmpPlayer->getPlayerName().c_str()) == 0)
				{
					//std::cout << (*it)->getPlayerName().c_str() << std::endl;
					PlayersOnline.erase(it);
					//ClientsOnline.erase(itOnline);

					//delete tmpPlayer;
				}
			}
		}
	}
	return 0;
}

To jest taki kod pisany na szybko, problem w tym, że w ostatniej pętli dostaję crash serwera. Po timeoucie użytkownika zamiast go usunąć, serwer się sypie, błąd jest związany z wektorem (bodajże out of range).
Czytałem, że nie mogę usuwać w pętli z wektora w którym pętla jest, dlatego stworzyłem wektor tymczasowy, ale i tak się sypie. Prosiłbym o pomoc, jak mogę usunąć z wektora gracza (PlayersOnline.erase(it)), który dostał timeout.

Pozdrawiam i z góry dziękuję za wskazówki.

0

Małe poprawki, kod wygląda teraz tak:

DWORD WINAPI Pingowanie(PVOID pvParam)
{
	PlayerVector tmpPlayersOnline; 
	ClientVector tmpClientsOnline;

	while(true)
	{
		Sleep(3000);
		Player* player = NULL;
		for(Piterator pit = PlayersOnline.begin(); pit != PlayersOnline.end(); pit++)
		{
			(*pit)->addPlayerPing();
			for(Citerator cit = ClientsOnline.begin(); cit != ClientsOnline.end(); cit++)
			{
				if((*pit)->getPlayerId() == (*cit).ID)
					(*cit).Send(4, "P");
			}

			if((*pit)->getPlayerPing() > 2)
			{
				if(strcmp((*pit)->getPlayerName().c_str(), (*pit)->getPlayerName().c_str()) == 0)
					tmpPlayersOnline.push_back(*pit);
			}

		}

		Player* tmpPlayer = NULL;
		for(Piterator it = tmpPlayersOnline.begin(); it != tmpPlayersOnline.end(); it++)
		{
			tmpPlayer = tmpPlayer->getPlayerById((*it)->getPlayerId());
			if(tmpPlayer)
			{
				if(strcmp((*it)->getPlayerName().c_str(), tmpPlayer->getPlayerName().c_str()) == 0)
				{
					//std::cout << (*it)->getPlayerName().c_str() << std::endl;
					PlayersOnline.erase(it);
					//(*itOnline).Disconnect();
					//ClientsOnline.erase(itOnline);

					//delete tmpPlayer;
				}
			}
		}
	}
	return 0;
}

Zapomniałem przede wszystkim wyczyścić wektory po poprzednim teście, w kodzie powyżej wektory tmp otrzymywały na początku wartość z wektorów globalnych.

0
for(Piterator it = tmpPlayersOnline.begin(); it != tmpPlayersOnline.end(); )
{
	tmpPlayer = tmpPlayer->getPlayerById((*it)->getPlayerId());
	if(tmpPlayer && strcmp(...) == 0)
	{
		it = PlayersOnline.erase(it);
	}
	else ++it;
}
0

@_0x666_ a jesteś pewnien że to bezpieczne? Mnie się jedynak wydaje że nie, bo dokumentacja twierdzi ze erase:

This invalidates all iterator and references to elements after position or first.

A jako że element it jest już usunięty z vectora to mam wątpliwości czy wolno nam go sobie ++ licząc na to ze przesunie się na odpowiednie miejsce.

1 użytkowników online, w tym zalogowanych: 0, gości: 1