2012-12-03 6 views
6

Ich habe kürzlich an der Entwicklung eines benutzerdefinierten Zuordners gearbeitet, der auf einem Speicherpool basiert, der von mehreren Instanzen des Zuweisers gemeinsam genutzt wird.Konflikte bei STL-Containern, SBO und benutzerdefinierten Zuordnern

Die Absicht war, dass der Verteiler mit STL und Standard C++ basierte Container wie Vektor, deque, Karte, string etc

jedoch etwas Bestimmtes verursacht hat mir einige Verwirrung kompatibel sein. Verschiedene Implementierungen der Container wie Std :: Vector, Std :: String nutzen Small Buffer Optimization - Stack-basierte Zuordnung für kleine anfängliche Speicheranforderungen.

Zum Beispiel MSVC9.1 hat das folgende Element in der basic_string Klasse:

union _Bxty 
{ // storage for small buffer or pointer to larger one 
    _Elem _Buf[_BUF_SIZE]; 
    _Elem *_Ptr; 
    char _Alias[_BUF_SIZE]; // to permit aliasing 
} _Bx; 

ich nicht sehen kann, wie wenn solche Behälter Instanziieren einer die Implementierung nur und immer verwenden Sie den mitgelieferten allocator schmeicheln kann und nicht SBO verwenden. Ich frage, weil einer der Absichten der Implementierung benutzerdefinierte Zuweisungen war in der Lage, sie in einem gemeinsamen Speicher Kontext zu verwenden, wo die Menge des gemeinsamen Speichers weniger als der SBO-Grenze einige der verschiedenen Implementierungen verwenden können.

Zum Beispiel würde Ich mag eine Situation haben, wo ich zwei Instanzen von std haben :: string eine pro Prozess einen gemeinsamen Block Speicher teilen, die vielleicht kleiner als oder gleich dem SBO oberen Grenze.

Möglicherweise verwandte: May std::vector make use of small buffer optimization?

typedef std::vector<int,mysharedmemallocator> shmvtype; 

shmvtype v(2,0); //<-- if SBO then error as memory is allocated on 
       //stack not via the allocator 

v[1] = 1234; //<-- if SBO then error as wrong piece of memory 
       // is being modified. 

Lässt ein anderes Beispiel, die auf gemeinsam genutzten Speicher nicht basiert, wie es Dinge für einige Menschen über zu erschweren scheint. Nehmen wir an, ich möchte meinen std :: basic_string oder std :: vector usw. mit einem Zuordner spezialisieren, der den Speicher füllt, den er mit dem Wert 0xAB reserviert, bevor er den Zeiger zurück zu der aufrufenden Einheit für keinen anderen Grund als launisch präsentiert.

Ein Container, der auf diesen neuen Zuordner spezialisiert ist, aber auch SBO verwendet, wird seinen SBO-basierten Speicher nicht mit 0xAB-Muster gefüllt haben. So zum Beispiel:

typedef std::basic_string<char,myfillmemallocator> stype 

stype s; 
s.resize(2); 

assert(s[0] == 0xAB); // if SBO this will fail. 

Antwort

4

einer der Absichten von benutzerdefinierten Verteilern Umsetzung war sie in einem Shared-Memory-Kontext in der Lage seine

Dies kann sein, was Sie damit zu tun beabsichtigen, zu verwenden, aber deshalb existieren sie nicht. In der Tat, mit Ausnahme von basic_string in C++ 98/03, ist es nicht zulässig, teilen zugewiesenen Speicher zwischen Objekten überhaupt. Sie können Zuweisungsobjekte teilen, damit sie ihren Speicher vom selben Ort beziehen können. Aber es ist illegal, wenn Modifikationen eines Objekts sich auf andere auswirken, die nichts miteinander zu tun haben; Jede Instanz muss separat sein.

Copy-on-Write-Strings funktionieren nur, weil das System annimmt, dass jeder nicht-konstante Zugriff auf ein Zeichen auf es schreiben wird, wodurch eine Kopie erstellt wird. Und in C++ 11 ist es sogar basic_string verboten, so etwas wie das Schreiben im Stil von Copy-on-Write zu machen.

Zum Beispiel möchte ich eine Situation haben, in der ich zwei Instanzen von std :: string eins pro Prozess haben kann, die einen gemeinsamen Speicherblock teilen, der kleiner oder gleich dem oberen SBO-Grenzwert ist.

Das ist nicht möglich, ohne Ihre eigene Klasse zu schreiben. Der Zuordner steuert nur, wo der Speicher herkommt. Was Sie wollen, ist eine garantierte Kopie-auf-schreiben-Zeichenfolge oder eine Art gemeinsamer Zeichenfolgenklasse.

Was Sie wollen, erfordert eine speziell für diesen Zweck konzipierte Containerklasse.

+1

Danke für den Kommentar Nicol, aber nur eine Frage, kann man nicht einen Zuordner haben, der Shared Memory zuweist, und Aliase den Speicher über ein Offset-Zeiger-Konzept - So wird es normal gemacht (boost.interprocess), nicht Sicher verstehe ich, warum es nicht getan werden kann. –

+2

@Seminar: Und was passiert, wenn Sie diese Zeichenfolge kopieren? Was passiert, wenn Sie ein Zeichen in diese Zeichenfolge einfügen und dadurch eine Neuzuweisung verursachen? Es ist nicht klar, was die Semantik einer dieser Operationen sein sollte, aber eines ist klar: Was auch immer die Semantik ist, sie sind Semantiken, über die die Implementierung selbst Bescheid wissen muss. Das heißt, Sie benötigen eine bestimmte Containerimplementierung, die die Dinge auf eine bestimmte Art und Weise erledigt. –

+1

In Bezug auf Kopieren von der gemeinsamen Zeichenfolge in eine andere Zeichenfolge ist eine gemeinsame Kopie, die Zielzeichenfolge wird nicht erwartet, gemeinsam genutzten Speicher zu haben, dies ist auch das gleiche umgekehrt, Kopieren von normalen Std :: String zu Shared String Daten wird kopiert in den geteilten Speicher, der vom spezialisierten Zuordner bereitgestellt wird - Das ist also für die Frage –

Verwandte Themen