2017-04-23 159 views
-2

我目前正在制作一款使用SDL2的游戏,并且我开始使用计时器,并且设置了一个调用SDL_CreateTextureFromSurface的函数的回调函数。然后我在线看到SDL_CreateTextureFromSurface只能从主线程调用,所以我建立了一个队列系统,在这个系统中,定时器线程可以将请求添加到调用SDL_CreateTextureFromSurface的队列中,并且主线程通过队列并实际调用它。当我尝试为定时器线程上的队列添加功能以及主线程创建一个互斥体并处理一个条目时,我的问题正在发生。使用多线程崩溃

我为SDL_CreateTextureFromSurface创建了一个包装,将条目添加到队列中。

multithread_protection.cpp(函数从计时器线程调用):

#include "multithread_protection.h" 
#include <SDL.h> 


#include <mutex> 

std::mutex mutex; 

bool bQueueCurrentlyProcessing = false; 
std::vector<function_t> queue; 

SDL_Texture * SDLCALL Queue_SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface) 
{ 
mutex.lock(); 

function_t func; 
func.renderer = renderer; 
func.surface = surface; 
func.pOutput = 0; 

if (queue.size() == 0) 
{ 
    func.id = 0; 
} 
else if (queue.size() > 0) 
{ 
    func.id = queue[queue.size() - 1].id + 1; 
} 

queue.push_back(func); 

mutex.unlock(); 

while (true) 
{ 
    mutex.lock(); 

    for (int i = 0; i < queue.size(); i++) 
    { 
     if (queue[i].id == func.id) 
     { 
      // This entry is validated as the one that we put in. 

      if (queue[i].pOutput) 
      { 
       SDL_Texture *pOutputCopy = queue[i].pOutput; 
       ////bQueueCurrentlyProcessing = true; 
       ////queue[i].acknowledged_completed = true; 
       //if (!pOutputCopy) 
       //{ 
       // int a; 
       // a = 5; 
       //} 

       return pOutputCopy; 
       return 0; 
      } 

      i = 0; 
     } 
    } 
    mutex.unlock(); 
} 


} 

multithread_protection.h:

struct function_t 
{ 
SDL_Renderer * renderer; 
SDL_Surface * surface; 
unsigned int id; 

SDL_Texture *pOutput; 
bool acknowledged_completed = false; 
}; 

extern bool bQueueCurrentlyProcessing; 
extern std::vector<function_t> queue; 

extern std::mutex mutex; 

SDL_Texture * SDLCALL Queue_SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface); 

render.cpp(主线程):

void HandleMultithreadedFunctionQueue() 
{ 
mutex.lock(); 

//bQueueCurrentlyProcessing = true; 
for (int i = 0; i < queue.size(); i++) 
{ 
    if (queue[i].pOutput == 0) // This entry hasn't been processed yet. 
    { 
     queue[i].pOutput = SDL_CreateTextureFromSurface(queue[i].renderer, queue[i].surface); 
    } 
    if (queue[i].acknowledged_completed) 
    { 
     //queue.erase(queue.begin() + i); // Erase entry from queue since it finished, and we don't need it anymore. 
    } 
} 
//bQueueCurrentlyProcessing = false; 

mutex.unlock(); 
} 

的互斥不断崩溃程序,有时会造成怪异的阻塞。如果有人可以请告诉我如何更好地处理这种多线程的情况,那会很好。谢谢!

编辑: 我试过使用std :: lock_guard,std :: unique_lock和std :: condition_variable,但可悲的是没有运气。也许我在我的情况下错误地使用它们?有人可以给我一些如何在我的情况下使用它们的例子吗?谢谢。

+2

对于RAII样式的锁定和解锁,使用'std :: lock_guard'。 – molbdnilo

+0

避免像瘟疫一样的手动锁定和解锁。你可能需要'std :: unique_lock'和'std :: condition_variable'的组合。 –

回答

1

使用全局变量和手动互斥锁/解锁是各种线程问题的坚实基础。例如,在return pOutputCopy;锁定的互斥锁未解锁,导致挂起和未定义的行为,当它被同一个线程再次锁定时。至少使用::std::lock_guard来处理互斥锁。