Frage

ich eine Klasse mit statischer Methode habe, die eine lokale statische Variable hat. Ich möchte, dass Variable berechnet werden / ausgewertet einmal (das erste Mal, dass ich die Funktion aufrufen) und für jeden nachfolgenden Aufruf, wird es nicht mehr ausgewertet. Wie geht das? Hier ist meine Klasse:

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;
    }
};

EDIT:

Danke alle für Ihre prompte Hilfe. 1 für alle. Ich wählte Antwort Tyler McHenrys, weil es keinen Vergleich braucht, rein statische Funktion Auswertung. Ich werde diesen Code für allocator müssen so vermeiden eine andere „wenn“ besser sein sollte. Nochmals vielen Dank!

EDIT:

gf Antwort stellte sich heraus, das beste zu sein, wie es mit der Zuordnung während der Kompilierung Zeit beschäftigt und speichert das Programm von Thread-sicher Kopfschmerzen und explizite Initialisierung. Allerdings respektiere ich die vorherige beste Antwort. Ich werde Kredit hier statt der Änderung der Häkchen geben. Vielen Dank an alle für die Hilfe!

War es hilfreich?

Lösung

Machen Sie eine weitere statische Funktion, die die Berechnung der Fall ist, und die Verwendung der für die Initialisierung der Variablen, z.

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;
}

Statische Variablen sind garantiert genau einmal initialisiert werden (zum ersten Mal die Funktion sie wird verwendet, enthält).

Edit: Das ist aber nicht Thread-sicher. Diese Seite erklärt, warum im Detail .

Um es Thread-sicher, es nicht ausreicht, um die Initialisierung von totalSize (der Anruf an computeSize) in einem kritischen Abschnitt zu wickeln, weil statische Variable Initialisierung „Compiler Magie“ ist, und es kann sein, dass die Variable erfährt Initialisierung jederzeit während des Anrufs getSize, bevor es verwendet wird, noch bevor die erste Anweisung der Funktion. Was Sie tun müssen, ist zu verhindern mehr als ein Thread von selbst getSize zugleich Aufruf, der mit einem weiteren Dereferenzierungsebene erreicht werden kann, z.

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;
}

Dies verhindert, dass zwei Fäden aus sogar die Funktion der Eingabe, die die statischen Variable in der gleichen Zeit enthält, und sicherzustellen, dass seine Initialisierung in einem kritischen Abschnitt eintreten wird.

Andere Tipps

Bewegen Sie die Berechnung in eine Hilfsfunktion:

static uint32_t totalSize = calculateTotalSize();

Die Hilfsfunktion nur in Anspruch genommen werden, wenn totalSize initialisiert wird.

Ein bisschen spät, aber warum tun Sie eine (potentiell) Laufzeitberechnung hier überhaupt? Verwenden Kompilierung-Konstanten und Sie können nicht einmal alle Threadingprobleme haben:

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;
}

So etwas wie:

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

würde den Trick tun. Beachten Sie, dass es nicht Thread-sicher ist.

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
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top