1

ローカル静的変数を持つ静的メソッドを持つクラスがあります。その変数を 1 回 (関数を初めて呼び出すとき) 計算/評価し、その後の呼び出しでは評価されないようにしたいと考えています。どうやってするか?これが私のクラスです:

template<
    typename T1 = int, unsigned N1 = 1,
    typename T2 = int, unsigned N2 = 0,
    typename T3 = int, unsigned N3 = 0,
    typename T4 = int, unsigned N4 = 0,
    typename T5 = int, unsigned N5 = 0,
    typename T6 = int, unsigned N6 = 0,
    typename T7 = int, unsigned N7 = 0,
    typename T8 = int, unsigned N8 = 0,
    typename T9 = int, unsigned N9 = 0,
    typename T10 = int, unsigned N10 = 0,
    typename T11 = int, unsigned N11 = 0,
    typename T12 = int, unsigned N12 = 0,
    typename T13 = int, unsigned N13 = 0,
    typename T14 = int, unsigned N14 = 0,
    typename T15 = int, unsigned N15 = 0,
    typename T16 = int, unsigned N16 = 0>
struct GroupAlloc
{
    static const uint32_t sizeClass;
    static uint32_t getSize()
    {
        static uint32_t totalSize = 0;

        totalSize += sizeof(T1)*N1;
        totalSize += sizeof(T2)*N2;
        totalSize += sizeof(T3)*N3;
        totalSize += sizeof(T4)*N4;

        totalSize += sizeof(T5)*N5;
        totalSize += sizeof(T6)*N6;
        totalSize += sizeof(T7)*N7;
        totalSize += sizeof(T8)*N8;

        totalSize += sizeof(T9)*N9;
        totalSize += sizeof(T10)*N10;
        totalSize += sizeof(T11)*N11;
        totalSize += sizeof(T12)*N12;

        totalSize += sizeof(T13)*N13;
        totalSize += sizeof(T14)*N14;
        totalSize += sizeof(T15)*N15;
        totalSize += sizeof(T16)*N16;

        totalSize = 8*((totalSize + 7)/8);

        return totalSize;
    }
};

編集:

迅速なご協力ありがとうございます。全員に+1。Tyler McHenry の回答を選択したのは、比較を必要とせず、純粋に静的な関数評価を行う必要があるためです。アロケーターにはこのコードが必要になるため、別の「if」を避ける方がよいでしょう。再度、感謝します!

編集:

gf の答えは、コンパイル時に割り当てを処理し、プログラムをスレッドセーフな頭痛と明示的な初期化から救うため、最良の答えであることが判明しました。ただし、前回のベストアンサーを尊重します。目盛りを変更する代わりに、ここでクレジットを与えます。助けてくれてありがとう!

4

4 に答える 4

4

計算を行う別の静的関数を作成し、それを変数の初期化に使用します。

static uint32_t computeSize() 
{
  uint32_t init_totalSize;

  // Lots of code

  return init_totalSize;
}

static uint32_t getSize()
{
  static uint32_t totalSize = computeSize();
  return totalSize;
}

静的変数は、一度だけ初期化されることが保証されています (それらを含む関数が最初に使用されるとき)。

編集:しかし、これはスレッドセーフではありません。このページでは、その理由を詳しく説明しています

totalSizeスレッドセーフにするためには、 (への呼び出し)の初期化をクリティカル セクションにラップするだけでは十分ではありません。これはcomputeSize、静的変数の初期化が「コンパイラ マジック」であり、実行中のいつでも変数が初期化される可能性があるためです。getSize関数の最初のステートメントの前であっても、使用される前の呼び出し。あなたがする必要があるのは、複数のスレッドgetSizeが同時に呼び出されないようにすることです。これは、さらに別のレベルの間接化で実現できます。

static uint32_t computeSize() 
{
  uint32_t init_totalSize;

  // Lots of code

  return init_totalSize;
}

static uint32_t real_getSize()
{
  static uint32_t totalSize = computeSize();
  return totalSize;
}

static uint32_t getSize()
{
  uint32_t totalSize;
  /* --- Enter Critical Section (acquire lock) -- */
  totalSize = real_getSize();
  /* --- Exit Critical Section (release lock) -- */
  return totalSize;
}

これにより、静的変数を含む関数に 2 つのスレッドが同時に入ることさえ防止され、その初期化がクリティカル セクション内で行われることが保証されます。

于 2010-03-20T12:00:50.997 に答える
3

計算をヘルパー関数に移動します。

static uint32_t totalSize = calculateTotalSize();

totalSizeヘルパー関数は、 gets が初期化されたときにのみ呼び出されます。

少し遅れましたが、なぜここで (潜在的に) 実行時間の計算を行っているのですか? コンパイル時の定数を使用すると、スレッドの問題さえ発生しません。

template<
  typename T1, unsigned N1,
  typename T2, unsigned N2,
  /* ... */
>
struct totalSize {
    static const uint32_t sum = 
        sizeof(T1)*N1
      + sizeof(T2)*N2
      /* ... */
      ;
    static const uint32_t value =
        8*((sum + 7)/8);
};

uint32_t GroupAlloc::getSize() {
    return totalSize<T1,N1,T2,N2,/*...*/>::value;
}
于 2010-03-20T11:59:31.077 に答える
2

何かのようなもの:

static uint32_t getSize()
{
    static uint32_t totalSize = 0;
    static bool computed = 0;
    if(computed)
      return totalSize;
    computed = 1;
    // ... go on with your computation

トリックを行うでしょう。スレッドセーフではないことに注意してください。

于 2010-03-20T12:01:33.660 に答える
2
static uint32_t totalSize = 0;    // initialisation performed once only
if ( totalSize == 0 ) {
        totalSize += sizeof(T1)*N1;
        totalSize += sizeof(T2)*N2;
        totalSize += sizeof(T3)*N3;
        totalSize += sizeof(T4)*N4;
        // etc
}
于 2010-03-20T12:02:16.953 に答える