SDL_AddTimer and streams, clearing the timer queue

I am writing an FFmpeg based media player and I have a design problem. My code calls a function to render video frames at irregular intervals using the SDL SDL_AddTimer function. My problem is that if I want to perform garbage collection when one video ends (or the playback stops) and the other starts, how can I make sure that I no longer have timers in the queue or in the middle of execution to avoid access to an object that is suddenly released.

+5
source share
1 answer

There are many different ways to solve your problem based on your specific implementation. A few basic ideas might be:

  • Define a boolean value that indicates whether the player is working (true = running, false = not)

  • Before each call related to the player, check this variable and, if it is false (the player is stopped), close the function (return immediately)

  • Then you call removeTimer and you set the variable to false to close the player.

However, since addTimer is a function that creates threads, race conditions can sometimes exist (what you called the "middle of execution"). This is one of the main problems when using threads.

You need to find and fix them using tools such as mutexes, semaphores, ... The choice of these tools largely depends on the strategy that you want to implement in order to avoid these race conditions.

So there is no general solution . If performance is not a concern, you can use this simple one-lock solution. This is the basic implementation of the critical section strategy. This prevents the launch of some fragments of code (closing the player and making critical sound calls).

 #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); } 

Of course, I cannot explain all race avoidance strategies in a simple stackoverflow article. If you need to improve performance, you must determine exactly what your concurrency issue is for your code and choose the right strategy.

+3
source

All Articles