7
votes

La bonne façon d'exposer un objet complexe de courte durée

Je développe une simulation d'évolution darwinienne. Pour des raisons de performance, il est écrit en C ++. La SIM est représentée par une instance de monde. Les animaux sont représentés par des cas d'animal, un objet assez compliqué. Le monde a deux méthodes importantes: xxx

et xxx

animal_at retourne un pointeur brut non nul à l'instance de l'animal qui représente le I -ème animal.
Evolue avance la simulation éventuellement invalidant tout pointeur renvoyé par animal_at . Je veux rendre la Sim et les animaux facilement accessibles de l'extérieur. J'ai des liaisons spécifiques à Python, mais j'envisage d'apprendre l'apprentissage de Corba ou de la glace pour mettre en œuvre une interface plus générique. Le problème est de savoir comment je devrais exposer les animaux. J'ai deux idées, dont aucune ne se sent satisfaisante: 1) Réécrivez légèrement le code pour utiliser Shared_PTR au lieu d'un PTR brut et utilisez un middleware qui comprend la sémantique partagée_ptr. 2) Générez un "proxy paresseux profond" qui a la même structure que l'animal. Ses membres seraient des mandataires aux membres de l'animal, de manière récursive. Animal_at serait réellement appelé au dernier moment avant de faire référence aux données réelles - le pointeur serait utilisé et jeté immédiatement. Cela impliquerait le «dernier moment» sémantique.

Je n'aime pas 1) parce que je devrais introduire un état de "zombie" de l'objet, qui me ressemble à l'habitude. Je n'aime pas 2) parce que le seul but du proxy est de mettre en œuvre le «dernier moment» sémantique.

Je cherche une manière non intrusive automatique (en utilisant la génération de code) pour y parvenir, car je Je ne veux pas obscurcir la signification du code d'origine. Y a-t-il un nom "officiel" pour ce que j'appelle "le dernier moment" sémantique?


0 commentaires

4 Réponses :


2
votes

Il y a une option d'utilisation de boost :: faible_ptr. Vous pouvez les transmettre, ils doivent utiliser le verrouillage () pour obtenir le sous-jacent Shared_PTR afin qu'ils puissent voir si l'objet n'existe plus.

La durée de vie de l'objet est déterminée uniquement par les endroits où se déroulent un partage_ptr. Il doit donc y avoir au moins un d'entre eux à tout moment pendant la durée de vie de l'objet et vous en avez besoin avant de créer un faible.


2 commentaires

Je vais avoir un regard plus près de Boost :: faible_ptr. La question est, comment va cet interplement avec Corba. Je ne veux pas apprendre Corba juste pour savoir que "Non, Corba ne supporte pas le dernier moment Sémantique". Merci pour la réponse.


Corba utilise son propre comptage de référence avec _VAR et ne prend pas en charge un concept d'un pointeur faible. Je pense que si vous utilisez un objet qui n'existe plus du côté serveur, vous obtenez une exception plutôt qu'un crash. Avec Corba, le concept est que tout le serveur pourrait descendre. Il existe une telle chose qu'une exception transitoire dans laquelle le serveur est en panne, mais les objets ont été créés avec la "persistance" de sorte qu'ils existeront lorsqu'il reviendrait à nouveau.



1
votes

Premièrement, vous pourriez envisager XML-RPC au lieu de CORBA en tant que middleware (plus d'utilisation standard de nos jours) .

Deuxièmement, les utilisateurs externes fonctionnent avec des données marshalérées. Ils envoient une référence marshaled sur le middleware et s'attendent à des informations sur la base de leur demande et de leur référence, donc je ne vois donc pas comment cela fonctionne avec «le dernier moment» de la slemagne et des pointeurs. Vous gardez soit tous vos animaux temporaires, les utilisateurs externes peuvent donc les interroger ou vous devez probablement envoyer beaucoup d'exceptions aux animaux non trouvés. (Ou vous les laissez demander le "dernier" animal)


3 commentaires

Pour des raisons de performance, je n'ai pas l'intention de marraler tout l'animal. Je souhaite que l'utilisateur externe puisse modifier les membres individuels, les membres des membres, peut-être même invoquer des méthodes de membres de membres, etc. est-ce que XML-RPC est adapté à la communication "naturelle" avec des objets C ++?


Si la référence est l'index i de l'animal (le même indice peut se référer à différents animaux à des moments différents), je dois générer la chaudière «proxy profond» (je refuse d'écrire une chaudière à la main pour des raisons idéologiques). Si la référence est liée à l'identité de l'objet, la partie serveur du middleware doit pouvoir déterminer si l'objet existe toujours (il devrait donc utiliser Boost :: faible_ptr ou ainsi).


XML-RPC n'est pas aussi "naturel" comme corba pour les objets, mais dans les objets finaux sont également passés par la référence de son objet Corba, donc par membre, vous auriez besoin d'un objet qui doit être enregistré / non enregistré et sa référence doit être passé.



1
votes

Si votre animal_at La fonction renvoie un pointeur qui peut être invalidé à tout moment à un moment donné, vous pouvez essayer de le renvoyer un pointeur intelligent (je suggérerais un partagé_ptr sur un faible_ptr ici, mais vous pouvez vous éloigner avec le pointeur faible si vous faites attention à la mise en œuvre). Cependant, au lieu de pointer directement à un objet animal , faites-le indiquer un boost :: optionnel objet. De cette façon, lorsque vous invalidez le pointeur, vous pouvez définir le drapeau invalide sur le pointeur et que tout utilisateur de l'objet nouvellement invalidé a la possibilité de vérifier si elles ont besoin d'obtenir un nouveau pointeur. < / p>


3 commentaires

Merci pour le boost :: indice en option, je vais y regarder.


Boost :: optionnel ici fait la même chose qui peut être fait par boost :: faible_ptr. Vous stockez votre boost :: Shared_PTR dans certains stockages centraux et boost de retour :: faible_ptr de animal_at. Vous venez de libérer Shared_ptr pour l'invalider. Chaque fois que vous souhaitez utiliser faim_ptr, vous devez "verrouiller" il: Si (boost :: Shared_ptr animal = animal_weak_ptr.lock ()) // pointeur est toujours valide, utilisez-le


@Robin Hood: J'ai déclaré que vous pourriez accomplir la même chose avec faible_ptr Avez-vous été prudent de la mise en œuvre. Utilisation d'un Shared_ptr > le rend simplement un peu plus lisible. Pour vérifier si le pointeur est toujours valide (contrôlé par l'objet de gestion), une pièce de code client aurait simplement besoin de vérifier la valeur de p-> valide . Comme toujours, il y a plus d'un moyen de peaufiner un chat ...



1
votes

Je ne comprends pas pourquoi vous souhaitez exporter un pointeur au lieu d'exporter une interface qui semble exactement le «dernier moment» sémantique que vous souhaitez. Votre animal_at pourrait renvoyer un objet id , pas un pointeur et l'interface donnerait à tous les accès requis à l'objet, tels que dosomething (id, paramètres) < / code>. L'interface pourrait également inclure des trucs de verrouillage / déverrouillage pour permettre l'accès atomique.


5 commentaires

Bon point sur l'accès atomique. Par "proxy profond", je veux dire exactement cette interface. Les appels ressembleraient à des animaux_proxy (5) .genome.genes [3] .Codones [6] .Dosomething (Param S) Cependant, je ne connais aucun outil pour autogénérer cette interface de la définition de l'animal.


@Pavel: Si votre cible est python, avez-vous considéré quelque chose comme Swig?


J'ai déjà des liaisons de python de travail (faites à l'aide de Py ++), mais je voudrais faire la simulation un composant n'importe quelle langue peut facilement communiquer avec.


@Pavel: Peut-être que je ne vois pas complètement ce que vous voulez, mais Swig soutient de nombreuses langues et est assez couramment utilisé


Pour Python, Py ++ analyse les sources C ++, donc pas besoin de se répéter rédiger le fichier d'interface. Cependant, je souhaite en faire un serveur qui peut être interrogé pour l'interface de manière standard (comme le référentiel d'interface de Corba). Je ne sais toujours pas si 1) ou 2) de ma question initiale est plus appropriée.