Cでシングルトンを作成する方法は?
-
03-07-2019 - |
質問
Cでシングルトンを作成する最良の方法は何ですか?並行ソリューションがいいでしょう。
Cは、シングルトンに使用する最初の言語ではないことを認識しています。
解決
まず、Cはオブジェクト指向プログラミングには適していません。そうすれば、あなたはずっと戦います。第二に、シングルトンはカプセル化された静的変数です。そのため、静的なグローバル変数を使用できます。ただし、通常、グローバル変数には関連する非常に多くの障害があります。それ以外の場合は、次のように関数のローカル静的変数を使用できます。
int *SingletonInt() {
static int instance = 42;
return &instance;
}
またはよりスマートなマクロ:
#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;
}
最後に、シングルトンはほとんど乱用されていることを忘れないでください。特にマルチスレッド環境では、それらを正しくするのは困難です...
他のヒント
する必要はありません。 Cにはすでにグローバル変数があるため、それらをシミュレートするための回避策は必要ありません。
C ++バージョンとほぼ同じです。インスタンスポインタを返す関数を用意するだけです。関数内の静的変数にすることができます。プラットフォームに応じて、クリティカルセクションまたはpthreadミューテックスで関数本体をラップします。
#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;
};
シングルトンを解放する関数も必要になることに注意してください。特に、プロセスの終了時に自動的に解放されないシステムリソースを取得する場合。
編集:私の答えは、あなたが作成しているシングルトンはやや複雑で、マルチステップの作成プロセスがあると仮定しています。静的なデータだけの場合は、他の人が提案したようなグローバルを使用してください。
Cのシングルトンは非常に奇妙です。 。 。 「オブジェクト指向C」の例を見たことがありません。特にエレガントに見えました。可能であれば、C ++の使用を検討してください。 C ++では、どの機能を使用するかを選択できます。多くの人は、これを「より良いC」として使用しています。
以下は、ロックフリーの1回限りの初期化の非常に典型的なパターンです。 InterlockCompareExchangePtrは、前の値がnullの場合、新しい値をアトミックにスワップします。これにより、複数のスレッドが同時にシングルトンを作成しようとしても、1つのスレッドだけが勝ちます。他のユーザーは、新しく作成されたオブジェクトを削除します。
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());
別の観点です:Cプログラムのすべてのファイルは、事実上、実行時に自動インスタンス化され、サブクラス化できないシングルトンクラスです。
- グローバルな静的変数はプライベートクラスのメンバーです。
- グローバル非静的はパブリックです(ヘッダーファイルで
extern
を使用して宣言するだけです)。 - 静的関数はプライベートメソッドです
- 非静的関数は公開されています。
すべてに適切なプレフィックスを付けると、 my_singleton.method()
の代わりに my_singleton_method()
を使用できるようになります。
シングルトンが複雑な場合は、使用前に generate_singleton()
メソッドを記述して初期化できますが、他のすべてのパブリックメソッドが呼び出されたかどうかを確認し、
やる
void * getSingleTon() {
static Class object = (Class *)malloc( sizeof( Class ) );
return &object;
}
コンカレント環境でも機能します。