10
votes

Modèle commun pour l'initialisation et l'arrêt de la bibliothèque?

existe-t-il un modèle que je peux utiliser pour appeler les routines d'initialisation et de nettoyage requises d'une bibliothèque sous-jacente (C)? Dans mon cas, je voudrais créer la classe wrapper afin qu'elle puisse être composée dans d'autres objets. Le problème est que lorsque je détruisez la classe wrapper, les routines de nettoyage de la bibliothèque sous-jacente sont appelées. C'est bon jusqu'à ce que j'instaine plusieurs objets de ma classe d'emballage. Ma question est de savoir ce qui est le meilleur moyen de vraiment gérer cette situation? Un compteur de référence statique vient à l'esprit, mais je voulais savoir s'il y avait d'autres options potentiellement meilleures et les métiers impliqués.


3 commentaires

Ce n'est pas une bonne idée, mais le modèle singleton aide-t-il?


Vous recherchez simplement le modèle utilisé par le STD :: ios_base :: init? Il initialise une bibliothèque C ++ (iOSTreams), mais la même chose pourrait fonctionner pour vous.


Une référence statique compte privé à votre classe wrapper sonne comme une belle solution pour moi.


5 Réponses :


4
votes

Tout ce qui doit être une classe. Le schéma Singleton vous permettrait de le transformer en une classe, mais cela ne vous achète vraiment rien sur les fonctions globales:

bool my_library_init();
void my_library_shutdown();


4 commentaires

Si je vous comprends correctement, cela fonctionnerait si je pouvais changer la bibliothèque sous-jacente. Dans ce cas, je ne peux pas.


Pas du tout. Écrivez vous-même ces deux fonctions globales, puis appelez-les. Il se peut que votre bibliothèque C sous-jacente fournit de telles fonctions elle-même. Principalement, je discute contre le genou-jerk "tout doit être une classe" penser. Je suis tout pour OOP où cela a du sens, mais je ne vois pas le sens ici.


Le travail que je fais est une bibliothèque. Je suis un client à la ressource partagée en question. Je veux abstraire les appels spécifiques de la bibliothèque sous-jacente de mon client. Il serait mauvais pratique de ne pas initialiser complètement l'objet que je crée dans la CTOR (initialisation partielle). Et si le client oublie d'appeler les appels d'initialisation ou d'arrêt? Ensuite, vous aurez (probablement) un comportement indéfini - pas une bonne chose.


Si vous avez un CTOR qui nécessite une initialisation d'une bibliothèque sous-jacente, initiez la bibliothèque dans cette CTOR. Simple.



6
votes

Si l'initialisation peut être appelée avant le début principal et le nettoyage appelé après extrémité principale, ce petit truc (piratage?) Peut fonctionner pour vous:

init
using library
fini


3 commentaires

Aussi Google pour l'ordre d'initialisation statique FIASCO. Par exemple, l'utilisation de std :: cout in init et fini a fait cette recrue c ++ nerveuse: est-elle garantie déjà / existe toujours ?


@Somebody: Ce n'était pas mon intention d'utiliser un objet global dans un autre objet statique, mais vous soulevez néanmoins un excellent point.


Merci, quelqu'un. Tu m'as fait renier de cette réponse pirate. ;-P



0
votes

Si vous pouvez modifier la mise en œuvre de la bibliothèque, vous pouvez avoir chaque appel à l'une des fonctions de la bibliothèque accéder à un singleton créé lors de la première utilisation.

ou vous mettez une variable globale / statique dans la bibliothèque qui l'initialise pendant la construction et la ferme pendant la destruction. (Cela pourrait devenir ennuyeux si la bibliothèque utilise des variables globales elles-mêmes et l'ordre d'initialisation / d'arrêt des conflits avec eux. En outre, les liens peuvent également décider d'éliminer les globaux non référents ...)

Sinon, je ne vois pas comment vous voulez éviter le comptage de référence. (Remarque Toutefois, il a l'inconvénient de créer plusieurs cycles d'init / arrêts au cours de la durée de vie du programme.)


0 commentaires

0
votes

Si votre ensemble de routines de bibliothèque C n'est pas trop grand, vous pouvez essayer de combiner le Singleton A > et Façade motifs de sorte que les routines de bibliothèque C ne soient appelées que via la façade. La façade assure l'initialisation et le nettoyage de la bibliothèque C. Singleton assure qu'il n'y a qu'une seule instance de la façade.

init
foo
bar
fini


5 commentaires

@Somebody: Nope, Façade :: Instance () n'est pas du thread-coffre-fort. Une solution de contournement facile (mais laid) serait d'appeler façade :: Instance () dans Main () avant que les threads soient engendrés. À ce moment-là, il semble que un peu stupide soit en train d'utiliser la façade, et vous pouvez également utiliser init / FINI directement dans MAIN.


J'aime comment ça me fait savoir sur les subtilités de la programmation.


Un pourrait faire façade :: Instance synchrone à l'aide de serrures, mais cela ajouterait beaucoup de contentions inutiles.


Merci, quelqu'un. Tu m'as fait renier de cette réponse pirate. ;-P


@Somebody thread La sécurité est essentiellement importante ici. Merci d'avoir attrapé ça.



1
votes

J'ai vu beaucoup de Singleton code> parler, donc je ne peux que recommander un coup d'oeil à travaux de Alexandrescu .

Cependant, je ne suis pas sûr que vous avez vraiment besoin d'un Singleton code> il . Parce que si vous le faites, vous supposez que tous vos appels vont partager l'état ... est-ce le cas? Voulez-vous vraiment quand vous appelez la bibliothèque par une autre instance de Wrapper code> pour obtenir l'état dans lequel le dernier appel fixé il? P>

Dans le cas contraire, vous devez sérialiser l'accès et les données ré-initialiser chaque fois. p>

class Wrapper
{
public:
  Wrapper() { lock(Mutex()); do_init_c_library(); }
  ~Wrapper() { do_clean_up_c_library(); unlock(Mutex()); }

private:
  static Mutex& Mutex() { static Mutex MMutex; return MMutex; }
}; // class Wrapper


0 commentaires