2013-05-23 17 views
7

Ich frage mich, können nur primitive Datentypen std :: atomic in C++ 11 deklariert werden? Ist es beispielsweise möglich, ein Bibliotheksklassenobjekt als "atomisch" mutiert zu erklären oder darauf zuzugreifen?C++ 11 Können nur primitive Datentypen als atomar deklariert werden?

Zum Beispiel, ich habe vielleicht

using namespace std::chrono; 
time_point<high_resolution_clock> foo; 

// setter method 
void set_foo() { 
    foo = high_resolution_clock::now(); 
} 

// getter method 
time_point<high_resolution_clock> get_foo() { 
    return foo; 
} 

Aber, wenn diese Setter und Getter-Methoden in verschiedenen Threads aufgerufen werden, denke ich, dass nicht definiertes Verhalten verursachen kann. Es wäre schön, wenn ich wie foo etwas erklären kann:

std::atomic<time_point<high_resolution_clock>> foo; 

... so dass alle Operationen auf foo in einer atomaren Weise durchgeführt werden würden. In der Anwendung für mein Projekt gibt es möglicherweise Hunderte von solchen foo Variablen über Dutzende von Klassen deklariert, und ich denke, es wäre viel bequemer, das Objekt mutieren und sozusagen "atomare", anstatt zu deklarieren und lock_guard Mutexes überall.

Ist das nicht möglich, oder gibt es einen besseren Ansatz, oder muss ich wirklich einen Mutex und lock_guard überall verwenden?

aktualisieren:

  • Jeder Abnehmer? Ich habe im Internet nach anständigen Informationen geforscht, aber es gibt so wenige Beispiele für atomare Anwendungen, von denen ich nicht sicher sein kann, in welchem ​​Umfang sie angewendet werden können.
+0

Std :: Atomic ist keine Problemumgehung für defekten Thread-Code. Wenn ein anderer Thread den Setter aufruft, wird der erste Thread, der ihn aufgerufen hat, sowieso einen Garbage-Wert vom Getter erhalten. –

Antwort

3

atomic<> ist nicht auf primitive Typen beschränkt. Es ist zulässig, atomic<> mit einem Typ T zu verwenden, also trivially copyable. Aus dem Bereich 29,5 Atomtypen des C++ 11-Standard (auch bei std::atomic angegeben):

Es gibt eine Vorlage Atomgenerische Klasse ist. Der Typ des Template-Arguments T soll trivial kopierbar sein (3.9).

Wenn die Objekte, für die Atom-Zugriff erforderlich ist, kann nicht mit atomic<> dann definieren neue Objekte verwendet werden, das ursprüngliche Objekt und ein std::mutex enthält. Dies bedeutet, dass lock_guard<> nur innerhalb des Getter- und Setter-Objekts des neuen thread-sicheren Objekts verwendet wird und nicht im gesamten Code verstreut ist. A template könnte Lage sein, die Sicherheitsgewinde Maschinen definieren erforderlich:

template <typename T> 
class mutable_object 
{ 
public: 
    mutable_object() : t_() {} 
    explicit mutable_object(T a_t) : t_(std::move(a_t)) {} 
    T get() const 
    { 
     std::lock_guard<std::mutex> lk(mtx_); 
     return t_; 
    } 
    void set(T const& a_t) 
    { 
     std::lock_guard<std::mutex> lk(mtx_); 
     t_ = a_t; 
    } 
private: 
    T t_; 
    mutable std::mutex mtx_; 
}; 

using mutable_high_resolution_clock = 
     mutable_object<std::chrono::time_point< 
      std::chrono::high_resolution_clock>>; 

using mutable_string = mutable_object<std::string>; 

mutable_high_resolution_clock c; 
c.set(std::chrono::high_resolution_clock::now()); 
auto c1 = c.get(); 

mutable_string s; 
s.set(std::string("hello")); 
auto s1 = s.get(); 
0

Atomics sind begrenzt auf trivially kopierbar Klassen (d.h. Klassen, die keine benutzerdefinierten Copykonstruktor haben, und deren Mitglieder auch trivially kopierbar).

Diese Forderung hat enorme Vorteile für atomics:

  • keine atomare Operation werfen kann, weil ein Konstruktor
  • warf
  • Alle atomics mit einem Schloss (spinlock oder Mutex) modelliert werden können und Memcpy Daten zu kopieren.
  • Alle Atome haben eine endliche Laufzeit (begrenzt).

Letzteres ist besonders nützlich, da atomics werden manchmal spinlocks implementiert, und es ist stark unbeschränkte Aufgaben zu vermeiden, während ein spinlock Halt gewünscht. Wenn ein Konstruktor erlaubt wäre, würden Implementierungen dazu neigen, auf vollständige Mutexe zurückzugreifen, die für sehr kleine kritische Abschnitte langsamer sind als Spinlocks.

Verwandte Themen