[SFML] Threads



  • Hallo

    Ich versuche mich im Moment an einem kleinen Spiel in SFML. Nun möchte ich Teile meiner Spielwelt im Hintergrund nachladen, währenddem man normal weiterspielt. Meine ersten Versuche bestanden darin, dass ich in meiner Hauptschleife einen sf::Thread erstelle und in diesem eine Methode der selben Klasse aufrufe (Game). Mein Problem ist nun jedoch, dass ich die meisten meiner Variablen meiner Game-Klasse in dieser Funktion verwende (z.B. eine Liste mit den geladenen Elementen).

    Wie kann man dies theoretisch anstellen? Ist es überhaupt möglich in Threads auf die selben Variablen zuzugreifen wie das Hauptprogramm (ohne alles auf static setzen zu müssen)?

    Vielen Dank
    StruktEd



  • Natürlich kannst du aus einem anderen Thread auf die Variablen des "Hauptprogramms" zugreifen, du musst dem Thread bloss einen Zeiger auf das Objekt mitgeben.
    Dummerweise musst du die Zugriffe dann aber auch synchronisieren.
    Und dann ist noch die Frage ob die SFML Funktionen die du verwendest um Bilder nachzuladen überhaupt threadsafe sind.



  • Vielen Dank für deine Antwort.

    Ich habe es jetzt wie von dir vorgeschlagen gemacht und dem Thread einen Zeiger auf die eigene Klasse mitgegeben. Dies funktioniert so weit eigentlich ordentlich.

    Was genau meinst du mit die Zugriffe synchronisieren (das ist der erste Versuch von mir mit Threads und SFML)? Verstehst du darunter, dass ich die Variablen für andere Zugriffe sperre? Dann wäre doch der Vorteil des Threads verloren? Oder sollte ich nur mit Kopien der Listen arbeiten und diese zum gegebenen Zeitpunkt (am Ende des Threads) in die richtigen Listen "mergen"?

    Gruss


  • Mod

    synchronisieren bedeutet dass du irgendwie sicherstellst, dass ein thread daten nicht halb modifiziert liest. wenn du z.b. ein std::vector<int> foo; hast thread 1 resized die auf n elemented, dann soll thread 2 diese lesen, waehrend thread 2 liest, resized thread 1 den vector auf 0. thread 2 wird dann unweigerlich jenseits der vectorgroesse lesen. wenn du mit .at(i) arbeitest, wird dein debugger stehenbleiben, wenn du nur [i] verwendest, wirst du stellenweise fehler haben die du dir nicht erklaeren kannst, sporadische abstuerze usw.

    man sollte also wirklich gut wissen was man macht, wenn man mit threads arbeitet. im einfachsten fall ist es besser die daten hin und her zu kopieren bzw an einem definierten punkt beide threads die pointer auf die double gepufferten daten austauschen zu lassen, als komplexe thread sychronization, denn 1. baut man ohne erfahrung wirklich fehler ein die schwer zu finden sind und 2. eine feiner synchronization, wie du schon erwaehnst, kann die ganzen vorteile von 2 threads zunichte machen (weil sie serialisiert sind und die serialisierung selbst zudem einen overhead hat).



  • @StruktEd

    Verstehst du darunter, dass ich die Variablen für andere Zugriffe sperre? Dann wäre doch der Vorteil des Threads verloren?

    Ja und jain.
    Du musst den Zugriff auf die Variablen ja z.B. nicht sperren während gerade ein Bild von der Platte geladen und dekodiert wird. Wenn du dann aber z.B. das geladene Bild in eine Liste einhängen willst, musst du zumindest für den Zeitraum des einhängens die Liste sperren.

    Oder sollte ich nur mit Kopien der Listen arbeiten und diese zum gegebenen Zeitpunkt (am Ende des Threads) in die richtigen Listen "mergen"?

    Schreib den Code für den Thread so, dass er möglichst wenig Dinge angreifen muss die auch im "Hauptprogramm" benötigt werden.
    Wenn du z.B. 10 PNGs laden willst, dann muss der Thread der das machen soll dazu ja nicht viel wissen - die Namen der 10 PNGs sollten reichen.
    Den Rest kannst du dann gleich im "Hauptprogramm" machen lassen - also z.B. den eigentlichen Texture-Upload.
    D.h. der Thread macht dann sf::Image::loadFromFile , und im Hauptprogramm machst du dann sf::Texture::loadFromImage .

    Wie einfach oder schwer ist das mit SFML aufzutrennen weiss ich nicht.

    Natürlich kann man, wenn man es richtig macht, auch das Erzeugen der Texturen + Texture-Upload in einem anderen Thread machen. Ich hab' aber keine Ahnung ob die SFML das unterstützt - also ob du in einem anderen Thread problemlos Texturen erzeugen kannst etc.



  • Vielen Dank für eure Antworten. Sie helfen mir sehr weiter. Ich denke, dass ich meinen Thread noch optimieren kann. Dies werde ich in den nächsten Tagen tun, wenn ich Zeit haben.

    Noch einmal vielen Dank
    StruktEd


Log in to reply