0

いくつかの数値で動作する C++ ライブラリがあります。この値はコンパイル時には利用できませんが、実行時にすぐに利用でき、マシン関連の詳細に基づいています。要するに、ディスプレイの解像度、CPU コアの数などの値が必要です。すぐ。

私の質問の要点は次のとおりです。

  • ユーザーにこの値を入力するように依頼することはできません (私のライブラリのコーダー/ユーザーと最終ユーザーの両方)
  • このウォームアップは、アプリケーションの起動時にのみ行う必要があります。これは 1 回だけです。
  • この値は後でメソッドとクラスによって使用されます

可能な解決策は次のとおりです。

  • データ構造を構築し、すべてを格納するために使用される変数の名前をData宣言しData dummydummyコンストラクターが関連する値の1回の初期化を処理します
  • 最初のソリューションのようなものを次のようなメソッドでラップし、WarmUp()このメソッドを開始直後に配置しmain()ます (覚えて使用するのも簡単です)

まだ解決されていない大きな問題は次のとおりです。

  • Dataこれは型であり、C++ で同じ型の 2-4-5-17 変数をスローすることについて制限がないため、ユーザーは複数のデータ構造を宣言できます。
  • メソッドはWarmUp()、他のクラスの設計に少し干渉する可能性があります。また、WarmUp()メソッドがローカル メソッドで使用され、main().

基本的に、ライブラリを実際に使用する権限がない場合、実行時に 1 つの特定の型の 1 つの単一インスタンスを強制的に作成する必要があります。ライブラリの使用をできるだけ直感的かつシンプルに保ちます。

これに対する解決策が見えますか?


編集:

マルチスレッド互換のデータ構造も取得しようとしているため、私の問題はより困難です。

4

3 に答える 3

2

遅延作成シングルトンを使用するのはどうですか? 例えば

struct Data
{
  static Data & instance()
  {
    static Data data_;
    return data_;
  }
private:
  Data()
  {
    //init
  }
}

Dataを呼び出すと、最初の使用時に初期化されますData::instance()

編集:マルチスレッドに関しては、C++で効率的なスレッドセーフなシングルトンを読んでください

boost::call_once を使用したEdit2 の実現

于 2013-04-05T07:48:05.103 に答える
0

まず、他の人が言ったように、これに対する明白な (そして最良の) 答えはシングルトンです。ただし、マルチスレッド要件を追加したため、オブジェクトがシングルトンを使用するコードによって変更されるかどうかに応じて、2 つの解決策があります。(あなたの説明から、私はそうではありません。)そうでない場合は、シングルトンの「ナイーブ」実装を使用し、スレッドが開始される前にシングルトンが初期化されるようにするだけで十分です。main に入る前にスレッドが開始されていない場合 (それ以外の場合は悪い習慣だと思います)、次のようなもので十分です。

class Singleton
{
    static Singleton const* ourInstance;
    Singleton();

    Singleton( Singleton const& );
    Singleton& operator=( Singleton const& );

public:
    static Singleton const& instance();
};

そして実装では:

Singleton const* Singleton::ourInstance = &Singleton::instance();

Singleton const&
Singleton::instance()
{
    if ( ourInstance == NULL ) {
        ourInstance = new Singleton;
    }
    return *ourInstance;
}

スレッド化が開始されるとスレッドは何も変更しないため、ロックは必要ありません。

シングルトンが変更可能な場合、シングルトンへのすべてのアクセスを保護する必要があります。上記のようなことを ( const明らかに なしで) 実行し、ロックをクライアントに任せることもできますが、そのような場合は、instance関数をロックしstd::shared_ptr、取得したロックを解放するデリータを使用して を返すことをお勧めします。instance関数で。次のようなものがうまくいくと思います(ただし、実際に必要になったことがないため、試していません):

class Singleton
{
    static Singleton* ourInstance;
    static std::mutex ourMutex;

    class LockForPointer
    {
    public:
        operator()( Singleton* )
        {
            Singleton::ourMutex.unlock();
        }
    };
    class LockForInstance
    {
        bool myOwnershipIsTransfered;
    public:
        LockForInstance
            : myOwnershipIsTransfered( false )
        {
            Singleton::ourMutex.lock();
        }
        ~LockForInstance()
        {
            if ( !myOwnershipIsTransfered ) {
                Singleton::ourMutex.unlock();
            }
        }
        LockForPointer transferOwnership()
        {
            myOwnershipIsTransfered = true;
            return LockForPointer();
        }
    };
public:
    static std::shared_ptr<Singleton> instance();
};

そして実装:

static Singleton* ourInstance = NULL;
static std::mutex ourMutex;

std::shared_ptr<Singleton>
Singleton::instance()
{
    LockForInstance lock;
    if ( ourInstance == NULL ) {
        ourInstance = new Singleton;
    }
    return std::shared_ptr<Singleton>( ourInstance, lock.transferOwnership() );
}

このようにして、null のチェックとデータへのアクセスに同じロックが使用されます。

于 2013-04-05T10:34:04.833 に答える
0

ウォームアップは通常、パフォーマンスの問題に関連しています (プロセッサ キャッシュについて考えさせられます。GCC の__builtin_prefetchを参照してください)。

シングルトン クラスを作成したい場合、これには多くの解決策があります (例:この C++ シングルトン チュートリアル)。

また、パフォーマンスが主な関心事である場合は、構成されたパラメーターが初期化時 (またはインストール時でさえも) に与えられると考えることができます。次に、適切な C++ スタブ ソース コードを (実行時 = 初期化時に) 発行し、それをコンパイル (「実行時」、たとえば初期化時) して動的にロードすることにより、最初にテンプレートを作成してインスタンス化するのと同じくらい簡単に、コードを特殊化できます。それ(プラグインを使用してdlopen...)。この回答も参照してください。

于 2013-04-05T07:49:34.160 に答える