2017-04-23 141 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來處理互斥鎖。