std::thread, comportement innattendu.
Salut,
je souhaite faire ceci :
-Endormir un thread jusqu'à qu'au moins un événement soit généré.
-Lorsque le thread est réveillé, l'endormir pendant quelque temps pour éviter les appels trop nombreux à lock et puis traiter un événement et ainsi de suite.
-Ensuite je souhaite bloqué les autres threads le temps du traitement d'un événement et les réveillé lorsque l'événement est traité.
J'ai donc fait quelque chose comme ceci.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#ifndef ODFAEG_ENTITY_SYSTEM_HPP
#define ODFAEG_ENTITY_SYSTEM_HPP
#include <condition_variable>
#include <mutex>
#include <thread>
#include "export.hpp"
#include <chrono>
/**
*\namespace odfaeg
* the namespace of the Opensource Development Framework Adapted for Every Games.
*/
namespace odfaeg {
/**
* \file entitySystem.h
* \class EntitiesSystem
* \brief base class of all entities systems of the odfaeg.
* \author Duroisin.L
* \version 1.0
* \date 1/02/2014
*/
class ODFAEG_CORE_API EntitySystem {
public :
/**
*\fn EntitySystem ()
*\brief constructor.
*/
EntitySystem () : needToUpdate(false) {
running = false;
g_notified = true;
}
/**
*\fn void launch()
*\brief launch the thread to update every entities of the entity system.
*/
void launch () {
running = true;
m_thread = std::thread (&EntitySystem::run, this);
}
/**
*\fn void update()
*\brief function called when we need to update the entities, this function block the current thread until it's finished.
*/
void update () {
if (!needToUpdate) {
g_notified = false;
needToUpdate = true;
g_signal.notify_one();
std::unique_lock<std::mutex> locker (g_lock_update);
g_signal.wait(locker, [&](){return g_notified;});
}
}
/**
*\fn void run()
*\brief this function block this thread until we need to update the entities by calling the update function.
* or if we want to stop the thread.
*/
void run () {
while (running) {
std::chrono::microseconds dura(100);
std::this_thread::sleep_for(dura);
std::unique_lock<std::mutex> locker(g_lock_update);
g_signal.wait(locker, [&](){return needToUpdate || !running;});
if (needToUpdate)
onUpdate();
g_notified = true;
needToUpdate = false;
g_signal.notify_all();
}
}
/**
*\fn bool isRunning()
*\brief tells is the thread is running.
*\return true if the thread is running.
*/
bool isRunning () {
return running;
}
/**
*\fn void stop()
*\brief stop this thread.
*/
void stop () {
running = false;
g_signal.notify_all();
}
/**
*\fn void onUpdate()
*\brief function to refefines to updates the entities.
*/
virtual void onUpdate() = 0;
private :
std::thread m_thread; /**< an internal thread which updates the entities*/
bool running, needToUpdate, g_notified; /**< tells if the thread is running, if the entities need to be update by the thread, and, if the thread have finished to update the entities.*/
std::condition_variable g_signal; /**<condition variable used for the primitive synchronisation of the thread.*/
std::mutex g_lock_update; /**<mutex used in the condition variable to avoid concurrent access to a variable between different threads*/
};
}
#endif // ENTITY_SYSTEM |
Cependant cela ne produit pas le comportement que je désire, je m'explique :
Les threads sont endormis avant que je fasse l'appel à g_signal.wait dans la boucle du thread, ce qui fais chuter mon FPS. :/ (Hors ça, je ne veux pas, je veux que les threads soit mis en attente après ce délai ci :
Code:
1 2 3
|
std::chrono::microseconds dura(100);
std::this_thread::sleep_for(dura); |
Et j'ai un crash également avec Xlib, voici ce qu'il m'affiche ceci :
Code:
1 2 3 4 5
|
[xcb] Unknow request in queue while dequeuing.
[xcb] Most likely this is a multi-thread client and XInitThreads has not been called
[xcb] Abording, sorry about that.
ODFAEG-DEMO: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion '!xcb_xlib_unknown_req_in_deq' failed. |
Bref, je ne sais plus trop quoi faire. :/