2013-05-24 5 views
8

Ich experimentiere mit der Aufrüstung unseres gepoolten Speicherblockzuweisungsspeichers, um die Eigenschaften von C++ 11-Typen zu nutzen.Kann der globale neue Operator basierend auf den Typeigenschaften des zugeordneten Objekts überschrieben werden?

Derzeit ist es möglich, jede Zuordnung eines Objekts zu zwingen, überall auf dem richtigen Pool zu versendenden von the global new operator auf traditionelle Weise überschreiben, zB

void* operator new (std::size_t size) 
{ // if-cascade just for simplest possible example 
    if (size <= 64) { return g_BlockPool64.Allocate(); } 
    else if (size <= 256) { return g_BlockPool256.Allocate(); } 
    // etc .. else assume arguendo that we know the following will work properly 
    else return malloc(size); 
} 

In vielen Fällen können wir die Leistung verbessern könnte weiter, wenn Objekte können in Abhängigkeit von Typmerkmalen wie is_trivially_destructible in verschiedene Pools gesendet werden. Ist es möglich, einen globalen globalen Template-Operator zu erstellen, der den zugewiesenen Typ kennt und nicht nur eine angeforderte Größe? Etwas entspricht

template<class T> 
void *operator new(size_t size) 
{ 
    if (size < 64) 
    { return std::is_trivially_destructible<T>::value ? 
      g_BlockPool64_A.Allocate() : 
      g_BlockPool64_B.Allocate(); } // etc 
} 

Aufschalten das Mitglied neuen Betreiber in jeder Klasse wird hier nicht funktionieren; wir brauchen das wirklich, um automatisch für jede Zuteilung überall arbeiten zu können. Platzierung neuer geht auch nicht: jedes alloc erfordern

aussehen
Foo *p = new (mempool<Foo>) Foo(); 

zu umständlich ist und die Menschen werden vergessen, es zu benutzen.

+1

Ordentliche Idee. Wie hilft es aber dem Speichermanager, wenn er einfach zerstörbar ist? Der Manager kümmert sich nicht um Konstruktion oder Zerstörung. – GManNickG

+0

@GManNickG Wenn alle trivial zerstörbaren Objekte in denselben Pool gehen, können wir sie massenweise freigeben, indem wir einfach die Speicherseite aufheben und keine Destruktoren aufrufen. Es ist ein OS-Aufruf statt Millionen von Deallocations. Nützlich, wenn alle Zuweisungen für einen Level Chunk in einen Block gehen und Sie das Ding einfach über Bord werfen können, wenn Sie diesen Bereich verlassen. Es gibt bereits andere Mechanismen, um zu verhindern, dass Menschen nach ihrer Lebenszeit Zeiger in diesen Block halten. – Crashworks

+0

Nein. Außerdem ist 'return :: new (size);' eine unendliche Rekursion. – aschepler

Antwort

3

Die kurze Antwort ist nein. Die Zuordnung/Freigabe-Funktionen haben folgende Unterschriften:

void* operator new(std::size_t); 
void* operator new[](std::size_t); 
void operator delete(void*); 
void operator delete[](void*); 

Die meisten Abweichungen von diesen Signaturen in Ihrer Funktion führen wird haupt nicht verwendet werden. In einer typischen Implementierung ersetzen Sie im Grunde genommen die Standardimplementierungen auf der Linker-Ebene - d. H. Die existierende Funktion hat einen bestimmten verfälschten Namen. Wenn Sie einer Funktion einen Namen geben, der zu einem identischen Ergebnis führt, wird sie stattdessen verknüpft. Wenn Ihre Funktion nicht den gleichen Namen hat, wird sie nicht verknüpft.

Eine Vorlage, wie Sie vorgeschlagen haben, könnte in einigen Fällen verwendet werden, aber wenn dies der Fall ist, würde dies zu undefiniertem Verhalten führen. Je nachdem, wie Sie zum Beispiel Kopfzeilen angeordnet haben, könnten Sie am Ende Code verwenden, der die Verwendung Ihrer Vorlage mit den Standardfunktionen mischt. An diesem Punkt wäre das Beste, auf das Sie hoffen könnten, dass es schnell und sauber abstürzt.

Verwandte Themen