J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
En cherchant un peu, j'ai trouvé ceci :
http://threadpool.sourceforge.net/tutorial/intro.html Ca
semble pas bien correspondre au cahier des charges au premier
abord, mais souvent les limitation n'apparaîssent que quand on
a déjà pas mal joué avec quelquechose.
J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
En cherchant un peu, j'ai trouvé ceci :
http://threadpool.sourceforge.net/tutorial/intro.html Ca
semble pas bien correspondre au cahier des charges au premier
abord, mais souvent les limitation n'apparaîssent que quand on
a déjà pas mal joué avec quelquechose.
J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
En cherchant un peu, j'ai trouvé ceci :
http://threadpool.sourceforge.net/tutorial/intro.html Ca
semble pas bien correspondre au cahier des charges au premier
abord, mais souvent les limitation n'apparaîssent que quand on
a déjà pas mal joué avec quelquechose.
Jean-Marc Desperrier wrote:J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Par thread « worker », j'entends un thread qui est lancé pour
effectuer un traitement particulier, et qui se termine à la fin
de ce traitement.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle sur
une attente à la queue. Tu passes l'objet fonctionnel par la
queue de messages. Ça doit faire moins de cinquante lignes de
code tout cassé.
Jean-Marc Desperrier wrote:
J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Par thread « worker », j'entends un thread qui est lancé pour
effectuer un traitement particulier, et qui se termine à la fin
de ce traitement.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle sur
une attente à la queue. Tu passes l'objet fonctionnel par la
queue de messages. Ça doit faire moins de cinquante lignes de
code tout cassé.
Jean-Marc Desperrier wrote:J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Par thread « worker », j'entends un thread qui est lancé pour
effectuer un traitement particulier, et qui se termine à la fin
de ce traitement.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle sur
une attente à la queue. Tu passes l'objet fonctionnel par la
queue de messages. Ça doit faire moins de cinquante lignes de
code tout cassé.
kanze wrote:Jean-Marc Desperrier wrote:J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Je trouve que c'est un peu dommage et que le besoin est
réellement répétitif. J'ai en tête une idée d'implémentation
en reprenant pratiquement preque à l'identique l'interface de
thread_group.
Par thread « worker », j'entends un thread qui est lancé
pour effectuer un traitement particulier, et qui se termine
à la fin de ce traitement.
Il s'agit exactement d'optimiser ce cas là.
Plutôt que de détruire à chaque fois le thread, le replacer
dans une liste de thread non-actif, et de manière transparente
reprendre l'un de ces thread pour gérer la prochaine requête.
Mais on se posera toujours un peu aussi la question de savoir
comment limiter le nombre de thread.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle
sur une attente à la queue. Tu passes l'objet fonctionnel
par la queue de messages. Ça doit faire moins de cinquante
lignes de code tout cassé.
Certe, mais 50 lignes un peu délicate.
kanze wrote:
Jean-Marc Desperrier wrote:
J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Je trouve que c'est un peu dommage et que le besoin est
réellement répétitif. J'ai en tête une idée d'implémentation
en reprenant pratiquement preque à l'identique l'interface de
thread_group.
Par thread « worker », j'entends un thread qui est lancé
pour effectuer un traitement particulier, et qui se termine
à la fin de ce traitement.
Il s'agit exactement d'optimiser ce cas là.
Plutôt que de détruire à chaque fois le thread, le replacer
dans une liste de thread non-actif, et de manière transparente
reprendre l'un de ces thread pour gérer la prochaine requête.
Mais on se posera toujours un peu aussi la question de savoir
comment limiter le nombre de thread.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle
sur une attente à la queue. Tu passes l'objet fonctionnel
par la queue de messages. Ça doit faire moins de cinquante
lignes de code tout cassé.
Certe, mais 50 lignes un peu délicate.
kanze wrote:Jean-Marc Desperrier wrote:J'aimerais bien implémenter un "thread pool" en me basant sur
boost, je me demande s'il y a des solutions à recommander.
Pourquoi ? C'est à résoudre quel problème ?
Il n'y a rien de particulier en ce qui concerne les « thread
pools ». Tout dépend de ce qu'on veut faire avec.
Je trouve que c'est un peu dommage et que le besoin est
réellement répétitif. J'ai en tête une idée d'implémentation
en reprenant pratiquement preque à l'identique l'interface de
thread_group.
Par thread « worker », j'entends un thread qui est lancé
pour effectuer un traitement particulier, et qui se termine
à la fin de ce traitement.
Il s'agit exactement d'optimiser ce cas là.
Plutôt que de détruire à chaque fois le thread, le replacer
dans une liste de thread non-actif, et de manière transparente
reprendre l'un de ces thread pour gérer la prochaine requête.
Mais on se posera toujours un peu aussi la question de savoir
comment limiter le nombre de thread.
Dans la contexte de Boost : tu crées une queue de messages à
partir de boost::mutex et de boost::condition. Tu en passes
l'adresse à chaque thread que tu crées ; le thread boucle
sur une attente à la queue. Tu passes l'objet fonctionnel
par la queue de messages. Ça doit faire moins de cinquante
lignes de code tout cassé.
Certe, mais 50 lignes un peu délicate.
Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
In news:,
kanze typed:Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
Si je comprends bien l'implementation de la MessageQueue, l'appel a
receive est bloquant. Donc le seul moyen de debloquer un thread, c'est
d'envoyer une fonction dans la queue qui passera la valeur de
shutdownRequested() a true. Mais ca ne debloque qu'un seul thread, les
(eventuels) autres restent a attendre sur le receive. Il faut donc
envoyer autant de fonctions de debloquage que de threads.
Il y a un moyen élegant (a mon gout) de resoudre ce probleme
avec le principe de la ActiveQueue de ACE. Grosso modo,
la queue a un etat (activé ou non), et le receive n'est bloquant
que si la queue est active. Quand on la desactive, les receive
se debloquent automatiquement, en retournant false:
La fonction de traitement devient:
void pooledThread(MessageQueue* queue )
{
boost::function0< void > f;
while (queue->receive(f))
{
f();
}
}
pour debloquer tous les threads immediatement, il suffit d'appeler
queue->deactivate();
qui peut tres bien etre traite sous forme de requete (on laisse le
temps de finir tous les traitements dans la queue):
queue->send(boost::bind(&MessageQueue::deactivate, queue));
La fonction receive doit ressembler a quelque chose comme ceci:
bool MessageQueue::receive(Fnc& f)
{
boost::mutex::scoped_lock lock( myMutex ) ;
if (m_state != ACTIVATED)
return false;
while (myQueue.empty() ) {
myCondition.wait( lock ) ;
if (myState != ACTIVATED)
return false;
}
f = myQueue.front() ;
myQueue.pop_front() ;
return true;
}
void MessageQueue::deactivate()
{
myState = ACTIVATED;
myCondition.notify_all();
}
In news:1151050564.909385.303550@b68g2000cwa.googlegroups.com,
kanze <kanze@gabi-soft.fr> typed:
Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
Si je comprends bien l'implementation de la MessageQueue, l'appel a
receive est bloquant. Donc le seul moyen de debloquer un thread, c'est
d'envoyer une fonction dans la queue qui passera la valeur de
shutdownRequested() a true. Mais ca ne debloque qu'un seul thread, les
(eventuels) autres restent a attendre sur le receive. Il faut donc
envoyer autant de fonctions de debloquage que de threads.
Il y a un moyen élegant (a mon gout) de resoudre ce probleme
avec le principe de la ActiveQueue de ACE. Grosso modo,
la queue a un etat (activé ou non), et le receive n'est bloquant
que si la queue est active. Quand on la desactive, les receive
se debloquent automatiquement, en retournant false:
La fonction de traitement devient:
void pooledThread(MessageQueue* queue )
{
boost::function0< void > f;
while (queue->receive(f))
{
f();
}
}
pour debloquer tous les threads immediatement, il suffit d'appeler
queue->deactivate();
qui peut tres bien etre traite sous forme de requete (on laisse le
temps de finir tous les traitements dans la queue):
queue->send(boost::bind(&MessageQueue::deactivate, queue));
La fonction receive doit ressembler a quelque chose comme ceci:
bool MessageQueue::receive(Fnc& f)
{
boost::mutex::scoped_lock lock( myMutex ) ;
if (m_state != ACTIVATED)
return false;
while (myQueue.empty() ) {
myCondition.wait( lock ) ;
if (myState != ACTIVATED)
return false;
}
f = myQueue.front() ;
myQueue.pop_front() ;
return true;
}
void MessageQueue::deactivate()
{
myState = ACTIVATED;
myCondition.notify_all();
}
In news:,
kanze typed:Pas si compliqué que ça : il s'agit en fin de compte
d'implémenter quelque chose de connu. Donc, la fonction qu'on
passe au constructeur de boost::thread pourrait bien ressemblait
à quelque chose comme :
void
pooledThread(
MessageQueue* queue )
{
while ( ! shutdownRequested() ) {
boost::function0< void >
f = queue->receive() ;
f() ;
}
}
Si je comprends bien l'implementation de la MessageQueue, l'appel a
receive est bloquant. Donc le seul moyen de debloquer un thread, c'est
d'envoyer une fonction dans la queue qui passera la valeur de
shutdownRequested() a true. Mais ca ne debloque qu'un seul thread, les
(eventuels) autres restent a attendre sur le receive. Il faut donc
envoyer autant de fonctions de debloquage que de threads.
Il y a un moyen élegant (a mon gout) de resoudre ce probleme
avec le principe de la ActiveQueue de ACE. Grosso modo,
la queue a un etat (activé ou non), et le receive n'est bloquant
que si la queue est active. Quand on la desactive, les receive
se debloquent automatiquement, en retournant false:
La fonction de traitement devient:
void pooledThread(MessageQueue* queue )
{
boost::function0< void > f;
while (queue->receive(f))
{
f();
}
}
pour debloquer tous les threads immediatement, il suffit d'appeler
queue->deactivate();
qui peut tres bien etre traite sous forme de requete (on laisse le
temps de finir tous les traitements dans la queue):
queue->send(boost::bind(&MessageQueue::deactivate, queue));
La fonction receive doit ressembler a quelque chose comme ceci:
bool MessageQueue::receive(Fnc& f)
{
boost::mutex::scoped_lock lock( myMutex ) ;
if (m_state != ACTIVATED)
return false;
while (myQueue.empty() ) {
myCondition.wait( lock ) ;
if (myState != ACTIVATED)
return false;
}
f = myQueue.front() ;
myQueue.pop_front() ;
return true;
}
void MessageQueue::deactivate()
{
myState = ACTIVATED;
myCondition.notify_all();
}