2010-05-01 2 views
6

C++ 0x Thread-Bibliothek oder Boost.thread definieren Nicht-Mitglied variadic Template-Funktion, die alle Sperre sperren Vermeidung von Dead-Lock.Warum gibt es keine Bereichssperren für mehrere Mutexe in C++ 0x oder Boost.Thread?

Während diese Funktion die Deadlock-Hilfe vermeidet, enthält der Standard nicht die zugehörige Bereichssperre zum Schreiben von Ausnahme-Sicherheitscode.

{ 
    std::lock(l1,l2); 
    // do some thing 
    // unlock li l2 exception safe 
} 

Das bedeutet, dass wir einen anderen Mechanismus als try-catch-Block zu machen Ausnahme sicheren Code oder definieren eigene scoped Sperre für mehrere mutexes uns oder sogar tun, dass

{ 
    std::lock(l1,l2); 
    std::unique_lock lk1(l1, std::adopted); 
    std::unique_lock lk2(l2, std::adopted); 
    // do some thing 
    // unlock li l2 on destruction of lk1 lk2 
} 

Warum die Standard verwenden müssen kein scoped Sperre auf mehrere mutexes desselben Typs enthält, wie beispielsweise

{ 
    std::array_unique_lock<std::mutex> lk(l1,l2); 
    // do some thing 
    // unlock l1 l2 on destruction of lk 
} 

oder Tupel von mutexes

{ 
    std::tuple_unique_lock<std::mutex, std::recursive_mutex> lk(l1,l2); 
    // do some thing 
    // unlock l1 l2 on destruction of lk 
} 

Ist etwas falsch am Design?


Aktualisiert: Beschreibung der Standard

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...); 

Benötigt: Jede Vorlage Parametertyp legt die Mutex Anforderungen erfüllen, mit Ausnahme, dass ein Anruf Sperre try_-() kann eine Ausnahme auslösen . [Hinweis: Die Template-Vorlage unique_lock erfüllt diese Anforderungen, wenn sie in geeigneter Weise instanziiert wird. -end note]

Effekte: Alle Argumente werden durch eine Folge von Aufrufen von lock(), try_lock() oder unlock() für jedes Argument gesperrt. Die Reihenfolge der Aufrufe darf nicht zu einem Deadlock führen, ist aber ansonsten nicht spezifiziert. [Hinweis: Ein Deadlock-Vermeidungsalgorithmus wie "try-and-back-off" muss verwendet werden, der spezifische Algorithmus wird jedoch nicht angegeben, um übermäßige Implementierungen zu vermeiden. -end note] Wenn ein Aufruf von lock() oder try_lock() eine Ausnahme auslöst, sollte unlock() für jedes Argument aufgerufen werden, das durch einen Aufruf von lock() oder try_lock() gesperrt wurde.


Ich habe die Antwort akzeptieren. Ich verstehe, dass der Hauptgrund ist, weil es nicht genug Zeit gibt, um die C++ 0x Thread-Bibliothek besser zu machen. Ich hoffe, dass TR2 viel mehr Dinge beinhaltet.

+1

Gute Frage, ich sehe nicht, warum gibt es nicht einige 'scoped_multi_lock (T ...)'. –

+1

In der Tat scheint es mir, die 'Lock (...)' Funktionen sind unausgewogen. Ich würde zumindest auch äquivalentes 'entriegeln (...) 'erwarten. Es scheint jedoch, dass der beste Ort, um solche Funktionalität hinzuzufügen, wäre die 'lock_guard' Klasse. Wobei es mit mehreren Lockables aufgebaut werden kann und diese bei Zerstörung freischalten. Im Gegensatz zu einem Haufen mehr Template-Klassen. – GrafikRobot

+0

@Grafik Sie haben Recht. Entsperren sollte auch auf dem Standard sein. Der Unterschied ist, dass Unlock (...) nicht blockieren kann. –

Antwort

3

Ich denke, dass durch die Bereitstellung defer_lock_t (und adopt_lock_t) die Erwartung, dass die Nutzung wie Ihr zweites Beispiel sein wird, ist, oder wahrscheinlich eher wie:

std::unqiue_lock ul1(l1, std::deferred); 
std::unique_lock ul2(l2, std::deferred); 
std::lock(ul1, ul2); 

Dies ist Ausnahme sicher und alles, was gute Sachen.

Ich kann sicherlich nicht vorgeben, die Köpfe der Designer zu kennen, aber ich schätze, dass sie sich bemühen, ein Minimum an tragbaren, sicheren, primitiven zu bieten.Ein Mehrfachverriegelungstyp ist nur so viel Vereisung, und es ist eine Vereisung, wenn im Standard spezifiziert und entworfen werden muss, oder in boost.thread, die Vereisung, die implementiert werden muss (und natürlich muss sich der Standard letztendlich Sorgen machen) Implementierung, schauen Sie, was mit dem Export passiert ist).

+0

"Export" ist eine völlig andere Kategorie und (hätte) große architektonische Änderungen in den Compilern. Warum denkst du, dass es so viel Zuckerglasur braucht? Es sollte nur einmal in Bezug auf die bereits gegebenen Primitiven geschrieben werden. –

+0

@Logan Sorry, ich mache den Fehler zu adoptieren statt Adopt_lock zu verwenden. –

+0

@gf, das ist irgendwie mein Punkt. Er schreibt _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '_ _ –

-1

Wenn Sie ein Objekt erstellen, das mehrere Sperren sperrt, werden keine Deadlocks vermieden, sondern nur diese einzeln gesperrt. Sie können nicht zwei Schlösser gleichzeitig sperren. Es sei denn, Sie verwenden zwei Fäden, die den Punkt besiegen. Dies gilt auch, wenn Sie sie in die gleiche Aussage setzen.

+3

Bitte beachten Sie den Standard. Es verwendet einen Algorithmus, der try_lock verwendet und diese Hilfe freigibt, um Deadlock zu vermeiden. In Fällen, in denen zwei Threads beide Protokolle verwenden, verwenden sie die gleiche Funktion. –

+0

Wie unterscheidet sich das OP nur von beiden selbst? Konnte sein, dass ich die Frage falsch gelesen habe, aber ich dachte, dass er vorschlug, dass, indem man solch eine Mehrfachverriegelungsstruktur hat, Sie offensichtlich sofort Deadlocks vermeiden würden, im Gegensatz zu, sie nacheinander zu sperren. – Puppy

+0

Nein, es ging um Ausnahmesicherheit und RAII Style Multi-Locks. Lesen Sie die Boost.Thread-Dokumentation oder den C++ 0x-Entwurf über 'lock()'. –

Verwandte Themen