2009-06-15 31 views
0

我正在研究廣泛使用多線程的模擬。事情是,直到現在,我從來沒有使用任何互斥對象來保護我的數據。其結果是,我得到一堆段錯誤的..C++/GLFW - 使用Mutex對象的正確方法?

我試圖鎖定/使用互斥解鎖時:讀/寫,但引起我的另一個段錯誤:

#0 77D27DD2 ntdll!RtlEnumerateGenericTableLikeADirectory() (C:\Windows\system32\ntdll.dll:??) 
#1 00000000 ??() (??:??) 

中當然,我創造,我應用鎖定/解鎖的事情基本情況的測試項目和它的工作,這裏是一個基本的例子,說明如何使用處理互斥對象GLFW:

#include <GL/glfw.h> 
#include <iostream> 
#include <vector> 

using namespace std; 

vector<int> table; 
GLFWmutex th_mutex; 
void GLFWCALL Thread_1(void* arg) { 


    glfwLockMutex(th_mutex); 
    table.pop_back(); 
    glfwUnlockMutex(th_mutex); 
} 

void GLFWCALL Thread_2(void* arg) { 

    glfwLockMutex(th_mutex); 
    table.erase(table.begin()); 
    glfwUnlockMutex(th_mutex); 

} 

int main() 
{ 

    bool running = true; 
    GLFWthread th_1, th_2; 

    glfwInit(); 

    if(!glfwOpenWindow(512, 512, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)) 
    { 
     glfwTerminate(); 
     return 0; 
    } 

    glfwSetWindowTitle("GLFW Application"); 

    for(int i = 0;i < 10; i++) { 
     table.push_back(i); 
    } 


    th_mutex = glfwCreateMutex(); 
    th_1 = glfwCreateThread(Thread_1, NULL); 
    th_2 = glfwCreateThread(Thread_2, NULL); 


    while(running) 
    { 

     // exit if ESC was pressed or window was closed 
     running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED); 
    } 

    glfwTerminate(); 

    return 0; 
} 

的項目,我工作更大,我有5個線程運行,並有很多向量,地圖,q ueues在同一時間被訪問。某處在代碼中,我試圖做這樣的事情:

void GLFWCALL CreateVehicleThread(void* arg) { 

    int index = (*static_cast<PulseStateByEntrance*>(arg)).index; 
    double t_initial = (*static_cast<PulseStateByEntrance*>(arg)).initial_time; 
    double t_final = (*static_cast<PulseStateByEntrance*>(arg)).final_time; 
    int pulse = (*static_cast<PulseStateByEntrance*>(arg)).pulse; 
    int nb_entrance = (*static_cast<PulseStateByEntrance*>(arg)).nb_entrance; 
    int min_time_creation = static_cast<int>(ceil(3600/pulse)); 


    while((glfwGetTime() - (*static_cast<PulseStateByEntrance*>(arg)).initial_time) 
    < ((*static_cast<PulseStateByEntrance*>(arg)).final_time - (*static_cast<PulseStateByEntrance*>(arg)).initial_time)) { 


      double t_elapsed = glfwGetTime() - t_initial; 


      if(t_elapsed > min_time_creation) { 

       **int nb_vehicle_per_cycle = static_cast<int>((t_elapsed * pulse)/3600); 
       glfwLockMutex(th_mutex); 
       VehicleManager::CreateVehicles(nb_vehicle_per_cycle, nb_entrance); 
       glfwUnlockMutex(th_mutex);** 
       t_initial = glfwGetTime(); 

      } 

    } 


} 

之所以,我把我的VehicleManager:CreateVehicles()鎖定/解鎖之間的方法是,因爲這種方法有這一行:

VehicleManager::vehicles_.push_back(vehicle); 

所以我想保護矢量:vehicles_。但是,結果我得到了上面的段錯誤。即使有:

glfwLockMutex(th_mutex); 
VehicleManager::vechicles_.push_back(vehicle); 
glfwUnlockMutex(th_mutex); 

我得到了相同的段錯誤。

我希望我已經讓自己清楚,足以讓你理解我的問題的本質。我想,並非所有人都與GLFW合作,這就是爲什麼我給了你第一個基本的例子,所以你可以理解互斥體如何與這個庫一起工作。

謝謝!

回答

1

你可以換你的容器,這將使你的代碼更容易理解:

template<typename T> 
class MultithreadedVector 
{ 
public: 
    void pushback(T data) 
    { 
     glfwLockMutex(m_mutex); 
     m_container.push_back(data); 
     glfwUnlockMutex(m_mutex); 
    } 
//then similar for erase etc 
private: 
    std::vector<T> m_container; 
    GLFWmutex m_mutex; 
}; 
1

沒有足夠的信息。但作爲猜測,它看起來像互斥體沒有正確創建(看起來像一個NULL引用)。找到調用glfwCreateMutex()的點並確保返回有效值。

不相關的問題,讓一個側面說明:

不這樣做:

glfwLockMutex(th_mutex); 
<ACTION> 
glfwUnlockMutex(th_mutex); 

這是C風格,因此也不例外安全。
您應該設置一個類,以便在構造函數中調用該鎖,並在析構函數中調用解鎖。然後有這個類的鎖對象。因此,鎖定和解鎖通常作爲對象創建結構的一部分發生,因此在出現異常時鎖定將被正確釋放。

princeiple是RAII,他們在這裏的主題很多文章。

例子:

class MutexLocker 
{ 
    public: 
    MutexLocker(GLFWmutex& mutex) 
     :m_mutex(mutex) 
    { 
     glfwLockMutex(m_mutex); 
    } 
    ~MutexLocker() 
    { 
     glfwUnlockMutex(m_mutex); 
    } 
    private: 
     GLFWmutex& m_mutex; 
}; 

void myAction() 
{ 
    MutexLocker lock(th_mutex); 

    // Do stuff here: 
} 
+0

你能幫我一個片段還是什麼?謝謝:) – 2009-06-15 19:18:21

+0

謝謝,我會試一試! – 2009-06-15 19:51:27

相關問題