Ich schreibe einen Media Player basierend auf FFmpeg und ich habe ein Design-Problem. Mein Code ruft eine Funktion zum Rendern von Videoframes in unregelmäßigen Intervallen auf, die mit der SDL-Funktion SDL_AddTimer erfolgt. Mein Problem ist das, wenn ich eine Garbage Collection durchführen möchte, wenn ein Video endet (oder die Wiedergabe gestoppt wird) und ein anderer startet, wie kann ich sicherstellen, dass ich keine Timer mehr in der Queue oder mitten in der Ausführung habe, um den Zugriff zu vermeiden Objekt, das plötzlich befreit wurde.SDL_AddTimer und Threading, Löschen der Timer-Warteschlange
Antwort
Es gibt viele verschiedene Möglichkeiten, um Ihr Problem basierend auf Ihrer spezifischen Implementierung zu lösen. Ein paar grundlegende Ideen sein können:
einen boolean definieren, die der Spieler gibt an, ob (true = läuft, false = nicht) läuft
Vor jedem Aufruf an den Spieler im Zusammenhang, überprüfen Sie die Variable und wenn es ist falsch (der Player ist gestoppt), schließen Sie die Funktion (sofort zurück)
Dann rufen Sie
removeTimer
und Sie setzen die Variable auf false, um den Player zu schließen.
Da jedoch addTimer
eine Funktion, die Threads erstellt ist, kann es manchmal Rennbedingungen (was man „die Mitte der Ausführung“ genannt). Es ist eines der Hauptprobleme, wenn Sie Threads verwenden.
Sie müssen diese mithilfe von Tools wie Mutexe, Semaphoren usw. finden und beheben. Die Auswahl dieser Tools hängt stark von der Strategie ab, die Sie implementieren möchten, um diese Race-Bedingungen zu vermeiden.
So gibt es keine generische Lösung. Wenn die Leistung keine Rolle spielt, können Sie diese einfache "One-Lock" -Lösung verwenden. Es ist eine grundlegende Implementierung der Strategie "kritischer Abschnitt". Es verhindert, dass einige Codeabschnitte (Schließen des Players und Ausführen von kritischen Sound-bezogenen Anrufen) gleichzeitig ausgeführt werden.
#include <pthread.h>
#include <stdbool.h>
pthread_mutex_t mutex;
bool isRunning;
int timerID;
void timerCallback(){
// do some computations
pthread_mutex_lock(&mutex);
// that critical section, defined here will never
// (thank to the mutex) occur at the same time at
// the critical section in the close method
if(isRunning){
// do critical calls
}
else{
// do nothing
}
pthread_mutex_unlock(&mutex);
// do some other computations
}
void init(){
pthread_mutex_init(&mutex, NULL);
isRunning = true;
startTimers();
}
void close(){
pthread_mutex_lock(&mutex);
// that critical section, defined here will never
// (thank to the mutex) occur at the same time at
// the critical section in the timerCallback method
SDL_RemoveTimer(timerID);
isRunning = false;
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
}
Natürlich kann ich nicht alle Rennen Anlage Vermeidungsstrategien in einer einfachen Stackoverflow Post erklären. Wenn Sie die Leistung verbessern möchten, sollten Sie genau definieren, was Ihr Nebenläufigkeitsproblem für Ihren Code ist, und die richtige Strategie auswählen.
Wie für "in der Mitte der Ausführung" Teil können Sie es mit z. Mutex. Ich bin mir nicht sicher, warum hier die Schlange steht, aber der Timer ist inaktiv. – keltar