Question

Quel est le meilleur moyen de créer un singleton en C? Une solution simultanée serait bien.

Je suis conscient que C n'est pas la première langue que vous utiliseriez pour un singleton.

Était-ce utile?

La solution

Tout d’abord, C ne convient pas à la programmation OO. Vous vous battriez si vous le faisiez. Deuxièmement, les singletons ne sont que des variables statiques avec une certaine encapsulation. Vous pouvez donc utiliser une variable globale statique. Cependant, les variables globales sont généralement associées à trop de maux. Vous pourriez sinon utiliser une variable statique locale de la fonction, comme ceci:

 int *SingletonInt() {
     static int instance = 42;
     return &instance;
 }

ou une macro plus intelligente:

#define SINGLETON(t, inst, init) t* Singleton_##t() { \
                 static t inst = init;               \
                 return &inst;                       \
                }

#include <stdio.h>  

/* actual definition */
SINGLETON(float, finst, 4.2);

int main() {
    printf("%f\n", *(Singleton_float()));
    return 0;
}

Et enfin, rappelez-vous que les singletons sont pour la plupart maltraités. Il est difficile de les obtenir correctement, surtout dans les environnements multithreads ...

Autres conseils

Vous n'avez pas besoin de. C a déjà des variables globales, vous n’avez donc pas besoin d’une solution de contournement pour les simuler.

C'est à peu près la même chose que la version C ++. Juste avoir une fonction qui retourne un pointeur d'instance. Ce peut être une variable statique à l'intérieur de la fonction. Enveloppez le corps de la fonction avec une section critique ou un mutex pthread, selon la plate-forme.

#include <stdlib.h>

struct A
{
    int a;
    int b;
};

struct A* getObject()
{
    static struct A *instance = NULL;

    // do lock here
    if(instance == NULL)
    {
        instance = malloc(sizeof(*instance));
        instance->a = 1;
        instance->b = 2;
    }
    // do unlock

    return instance;
};

Notez que vous auriez également besoin d’une fonction pour libérer le singleton. Surtout s'il récupère les ressources système qui ne sont pas automatiquement libérées à la sortie du processus.

EDIT: Ma réponse suppose que le singleton que vous créez est un peu complexe et comporte un processus de création en plusieurs étapes. S'il ne s'agit que de données statiques, optez pour une approche globale, comme l'ont suggéré d'autres personnes.

Un singleton en C sera très bizarre. . . Je n'ai jamais vu d'exemple de "C orienté objet". cela avait l'air particulièrement élégant. Si possible, envisagez d'utiliser C ++. C ++ vous permet de choisir les fonctionnalités que vous souhaitez utiliser, et de nombreuses personnes l’utilisent simplement comme "meilleur C".

Vous trouverez ci-dessous un modèle assez typique d’initialisation unique sans verrouillage. InterlockCompareExchangePtr bascule atomiquement dans la nouvelle valeur si la valeur précédente est null. Cela protège si plusieurs threads tentent de créer le singleton en même temps, un seul gagnera. Les autres supprimeront leur objet nouvellement créé.

MyObj* g_singleton; // MyObj is some struct.

MyObj* GetMyObj()
{
    MyObj* singleton;
    if (g_singleton == NULL)
    {
        singleton = CreateNewObj();

        // Only swap if the existing value is null.  If not on Windows,
        // use whatever compare and swap your platform provides.
        if (InterlockCompareExchangePtr(&g_singleton, singleton, NULL) != NULL)
        {
              DeleteObj(singleton);
        }
    }

    return g_singleton;
}

DoSomethingWithSingleton(GetMyObj());

Voici un autre point de vue: chaque fichier d'un programme C est en réalité une classe singleton instanciée automatiquement à l'exécution et ne peut pas être sous-classée.

  • Les variables statiques globales sont les membres de votre classe privée.
  • Les non statiques globaux sont publics (déclarez-les simplement en utilisant extern dans certains fichiers d'en-tête).
  • Les fonctions statiques sont des méthodes privées
  • Les fonctions non statiques sont les fonctions publiques.

Donnez à chacun un préfixe approprié et vous pouvez maintenant utiliser my_singleton_method () au lieu de my_singleton.method () .

Si votre singleton est complexe, vous pouvez écrire une méthode generate_singleton () pour l'initialiser avant de l'utiliser, mais vous devez ensuite vous assurer que toutes les autres méthodes publiques vérifient si le singleton a été appelé et en cas d'erreur. pas.

Il suffit de faire

void * getSingleTon() {
    static Class object = (Class *)malloc( sizeof( Class ) );
    return &object;
}

qui fonctionne également dans un environnement concurrent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top