Nebenläufigkeitsproblem ohne Threads

Der Wolf

Erfahrenes Mitglied
Hallo und guten Morgen,

ich habe in meinem aktuellen Projekt ein Problem, dass an einer Stelle ein Element aus einem std::vector gelöscht wird, auf das in einer ganz anderen Funktion aber noch zugegriffen wird, weil es bei Einstieg in diese Funktion noch da ist. Durch verschiedene Ausgaben habe ich herausgefunden, dass die beiden Funktionen anscheinend nebenläufig ablaufen, obwohl mein Programm ohne Threads arbeitet, aber von aussen angestoßen werden kann.

Hier mal Teile des Codes:

Code:
void
PersonControl::updatePersons() {

	// Erase all persons which are not updated
	// for a while.
	std::vector<Person*>::iterator it;
	for (it = persons.begin(); it != persons.end();) {

		uint64_t currentTime	= PerceptTime::getCurrentTime();
		uint64_t lastUpdate		= (*it)->getLastUpdate();

		if ((currentTime - lastUpdate) > MAXTIMEWOUPDATE) {

			debug << "One person erased." << std::endl;

			Person *person = (*it);

			// Erase person from scene memory.
			std::string xmlDoc = person->getXMLDoc();
			if (xmlDoc != "") {
				sceneControl->removeXMLDoc(xmlDoc);				
				inSceneMemory--;
			}

			// Erase person from list.
			it = persons.erase(it);					

			// Delete person.
			delete person;

			debug << "Person completly removed." << std::endl;

		} else {
	
			it++;

		}
	}
}

Die andere Methode in der ebenfalls auf der Liste gearbeitet wird, aus der die Person gelöscht wird ist etwas zu lang um sie hier zu posten, deshalb nur ein kleiner Ausschnitt:

Code:
	debug << "Number of persons: " << persons.size() << std::endl;	
	int currPerson = 0;
	for (it = persons.begin(); it != persons.end(); it++)	{
	
		Person *person = (Person*) (*it);

		if (person && assign[currPerson] >= 0) {

			debug << "Number of persons: " << persons.size() << std::endl;
			debug << "Person: " << currPerson << " gets percept " << assign[currPerson] << std::endl;

			person->getAnchor(type).assignPercept(*(pList.getPercept(assign[currPerson])), TOPDOWN);
			assigned[assign[currPerson]] = true;				

			debug << "Percept assigned." << std::endl;
	
			// Update person in the active memory or insert it if it is not in memory.
			int timesUpdated = person->getTimesUpdated();
			if (timesUpdated == MINNUMOFUPDATES) {

				std::string returnStr = sceneControl->strInsertToMemory(person->getDocument());
				person->setXMLDoc(returnStr);
		
				inSceneMemory++;

			} else if (timesUpdated > MINNUMOFUPDATES) {
				sceneControl->bReplaceWithDBXMLID(person->getDocument());
			}

		} else {

			person->getAnchor(type).assignNoPercept();

		}	

	currPerson++;

	}

Guckt man sich die Ausgaben an, so sieht man, dass das die Löschen-Methode an sich vor dem Eintritt in die untere Methode angestoßen, aber nicht zu Ende ausgeführt wird, was dazu führt, dass ein vector element beim durchlauf der Schleife irgendwann verloren geht und ich einen Seg-Fault bekomme.
Kann mir einer eine schicke und saubere Methode sagen, das zu verhindern?

Gruß und Danke im Vorraus
Der Wolf
 
Hallo, wenn diese Methoden offensichtlich parallel laufen musst du den Zugriff wohl über ein Mutex schützen z.b. aus der boost::library. Zur Not kannst aber auch eine globale Variable als Schalter benutzen. Ich finde es sehr merkwürdig das diese Methoden gleichzeitig in deinem sequentiellen Programm ablaufen sollen, vllt solltest du eher diese Ursache beseitigen.

mfg :D
 
Ich hätte ja auch nicht damit gerechnet, das die nebenläufig sind.
Aber wie gesagt, das ganze Programm wird von außen gesteuert. Es registriert sich auf einem active memory und jedesmal wenn da was inserted, replaced oder removed wird, wird das Programm benachrichtigt.
 
Hmm ... ok ... das ActiveMemory setzt allerdings threads ein, was zu der Nebenläufigkeit wohl führt. Reicht es dann wenn ich mit dem boost::scoped_lock arbeite? Bisher musste ich mich damit noch nicht auseinander setzen und da wären mir ein paar Tips recht, wie man sowas auf elegante und saubere Weise löst. :D

Gruß
Das Wolf
 
Hallo,

ja das würde reichen, ich geb dir mal ein Link wo das super beschrieben ist und was für Möglichkeiten du einsetzen kannst.
siehe hier

Wenn du nur eine Methode hast die schreibend und mehrere die lesend auf den Vector zugreifst lohnt sich aus Performance-Sicht der boost::shared_mutex den du mit #include <boost/shared_mutex.hpp> einbindest. Einfach eine Mutex Variable in die Klasse PersonControl als Member definieren und vor dem Zugriff den Mutex in Beschlag nehmen. Am besten den Abschnitt durchlesen ;)

mfg
 
Auf jedenfall schonmal vielen Dank. Ich habe jetzt in den beiden Methoden, die davon betroffen sind einfach am Anfang einen boost::scoped_lock gesetzt, was anscheinend die Probleme behoben hat.

LG
Der Wolf
 
Zurück