2009-07-24 11 views
7

Mon scénario: un serveur et quelques clients (mais pas beaucoup). Le serveur peut uniquement répondre à un client à la fois, ils doivent donc être mis en file d'attente. J'utilise un mutex (boost::interprocess::interprocess_mutex) pour ce faire, enveloppé dans un boost::interprocess::scoped_lock. Le fait est que si un client meurt de façon inattendue (c'est-à-dire qu'aucun destructeur ne s'exécute) tout en maintenant le mutex, les autres clients sont en difficulté, car ils attendent sur ce mutex. J'ai envisagé d'utiliser l'attente temporisée, donc si le client attend, disons, 20 secondes et ne reçoit pas le mutex, il va de l'avant et parle au serveur de toute façon.Comment devenir propriétaire d'un boost boosté :: interprocess :: interprocess_mutex?

Problèmes avec cette approche: 1) il le fait à chaque fois. Si c'est dans une boucle, en parlant constamment au serveur, il doit attendre le timeout à chaque fois. 2) S'il y a trois clients, et que l'un d'entre eux meurt en tenant le mutex, les deux autres attendent juste 20 secondes et parlent au serveur en même temps - exactement ce que j'essayais d'éviter.

Alors, comment dire à un client, "hey là, il semble que ce mutex a été abandonné, s'approprier"?

+2

Si vous comptez sur les clients pour effectuer la synchronisation, vous le faites en arrière. Vous devriez vraiment réparer votre serveur afin qu'il puisse accepter plusieurs connexions, même si cela ne fait qu'attendre les autres connexions pendant qu'elles servent une à la fois. Cela vous permet de sortir la partie * interprocess * de l'équation. –

+0

Fair point. Cependant, à l'origine, mon application avait été spécifiée comme ayant seulement un client à la fois - je n'ai découvert que récemment (comme aujourd'hui) qu'il pourrait y avoir plusieurs clients. J'ai essayé de le résoudre facilement, mais je suppose que je devrais trouver quelque chose de plus sophistiqué. –

+0

Il semble que tout le mécanisme du mutex soit défectueux sans mécanisme de récupération. Souhaits de boost corrige ceci. – balki

Répondre

6

Malheureusement, ceci n'est pas supporté par l'API boost :: interprocess tel quel. Il y a quelques façons dont vous pouvez la mettre en œuvre cependant:

Si vous êtes sur une plate-forme avec prise en charge POSIX pthread_mutexattr_setrobust_np, modifier boost/interprocessus/synchronisation/posix/thread_helpers.hpp et stimuler/interprocessus/synchronisation/posix/interprocess_mutex. hpp pour utiliser des mutex robustes, et pour gérer en quelque sorte le retour de EOWNERDEAD de pthread_mutex_lock. Si vous êtes sur une autre plate-forme, vous pouvez éditer boost/interprocess/sync/emulation/interprocess_mutex.hpp pour utiliser un compteur de génération, avec le drapeau verrouillé dans le bit le plus bas. Vous pouvez ensuite créer un protocole de récupération qui définira un indicateur dans le mot de verrouillage pour indiquer une demande de récupération en attente, puis effectuer une comparaison et un échange après un délai pour vérifier que la même génération figure toujours dans le mot de verrouillage. avec une valeur verrouillée de prochaine génération.

Si vous utilisez Windows, une autre bonne option serait d'utiliser des objets mutex natifs; ils seront probablement plus efficaces qu'attendus de toute façon.

Vous pouvez également reconsidérer l'utilisation d'un protocole de mémoire partagée - pourquoi ne pas utiliser un protocole réseau à la place?

+0

Bonne réponse. Je ne pense pas que je vais l'implémenter, cependant; ça ne semble pas en valoir la peine - je penserai à autre chose. À propos de votre suggestion d'utiliser un protocole réseau, je ne pourrais pas être plus d'accord avec vous. Malheureusement, il est trop tard pour changer radicalement les choses. –