2009-06-15 5 views
0

Я работаю над симуляцией, которая широко использует многопоточность. Дело в том, что до сих пор я никогда не использовал никаких объектов мьютекса для защиты своих данных. И результат, это то, что я получаю кучу ошибок сегментации ..C++/GLFW - Правильный способ использования объектов Mutex?

Я пытаюсь заблокировать/разблокировать с мьютекс в то время как: чтение/запись, но это вызывает у меня еще Segfault:

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

Of Конечно, я создал тестовый проект, в котором я применил блокировки/разблокировки вещь для базовой ситуации, и она работала, вот простой пример, который показывает, как иметь дело с объектами Mutex с помощью 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_. Но в результате я получил этот segfault выше. И даже с:

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

У меня такой же segfault.

Надеюсь, я достаточно четко дал понять, что вы понимаете природу моей проблемы. Полагаю, не все вы работали с 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; 
}; 
+0

Я нахожу его изящным, попробую! Благодаря ! –

1

Информация не достаточна. Но, как предполагалось, похоже, что мьютекс был создан неправильно (выглядит как ссылка NULL). Найдите точку, в которой вы вызываете glfwCreateMutex(), и убедитесь, что возвращается действительное значение.

не связаны с вашей проблемой поэтому сторона примечание:

не делать этого:

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

Это C стиль, и в результате не исключение безопасности.
Вы должны создать класс, чтобы вызвать вызов в конструкторе, и разблокировка вызывается в деструкторе. Затем создайте объект блокировки этого класса. Таким образом, блокировка и разблокировка происходят обычно как часть создания объекта, поэтому при наличии исключений блокировка будет правильно выпущена.

Принцесса - это 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

Можете ли вы помочь мне с сниппета или что-то? спасибо :) –

+0

Спасибо, я дам ему попробовать! –