2009-06-15 5 views
0

Ich arbeite an einer Simulation, die Multithreading ausgiebig verwendet. Die Sache ist, dass ich bis jetzt noch keine Mutex-Objekte benutzt habe, um meine Daten zu schützen. Und das Ergebnis ist, dass ich Bündel von Segmentation Faults bin immer ..C++/GLFW - Der richtige Weg, um Mutex-Objekte zu verwenden?

Ich versuche, mit Mutex zum Sperren/Entsperren während: Lesen/Schreiben, aber das macht mir ein anderes segfault:

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

Of natürlich habe ich ein Testprojekt erstellt, wo ich das Sperren/Entsperren, was für eine grundlegende Situation angewandt und es hat funktioniert, hier ist ein einfaches Beispiel, das zeigt, wie mit Mutex-Objekten behandeln GLFW mit:

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

Das Projekt, i arbeite ich ist größer, ich habe 5 Threads darauf laufen, und eine Menge von Vektoren, Karten, q auf sie wird gleichzeitig zugegriffen. Irgendwo im Code, habe ich versucht, so etwas wie zu tun:

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(); 

      } 

    } 


} 

Der Grund, warum, ich stelle meine VehicleManager: CreateVehicles() -Methode zwischen Sperren/Entsperren ist, weil bei diesem Verfahren gibt diese Zeile:

VehicleManager::vehicles_.push_back(vehicle); 

So wollte ich den Vektor schützen: vehicles_. Aber als Ergebnis habe ich diesen segfault oben. Und sogar mit:

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

ich bekam den gleichen segfault.

Ich hoffe, ich habe mich selbst klar genug gemacht, dass Sie die Natur meines Problems verstehen. Ich nehme an, nicht alle von Ihnen haben mit GLFW gearbeitet, deshalb habe ich Ihnen das erste grundlegende Beispiel gegeben, damit Sie verstehen können, wie Mutexe mit dieser Bibliothek arbeiten.

Danke!

Antwort

1

Sie Ihre Container wickeln können, die Ihren Code machen wird leichter zu verstehen:

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; 
}; 
+0

Ich finde es elegant, werde es versuchen! Vielen Dank ! –

1

Es gibt nicht genügend Informationen. Aber es sieht so aus, als wäre Mutex nicht korrekt erstellt worden (sieht wie eine NULL-Referenz aus). Suchen Sie den Punkt, an dem Sie glfwCreateMutex() aufrufen, und stellen Sie sicher, dass ein gültiger Wert zurückgegeben wird.

Nicht so eine Randnotiz Bezug auf Ihr Problem:

dies nicht tun:

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

Dieses C-Stil ist, und als Ergebnis nicht Ausnahme sicher.
Sie sollten eine Klasse einrichten, so dass die Sperre im Konstruktor aufgerufen wird und die Entsperrung im Destruktor aufgerufen wird. Dann habe ein Sperrobjekt dieser Klasse. Daher erfolgt das Sperren und Entsperren normalerweise als Teil der Objekterstellungs-Anweisung, daher wird die Sperre bei Vorhandensein von Ausnahmen korrekt freigegeben.

Der Printiple ist RAII und ihre sind viele Artikel zu diesem Thema hier.

Beispiel:

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

Können Sie mir helfen mit einem Code-Schnipsel oder so etwas? Danke :) –

+0

Danke, ich werde es versuchen! –

Verwandte Themen