2012-12-13 9 views
5

Ist es möglich, unique_ptr mit C++ 11 atomaren Operationen sicher zu verschieben?Thread sicher unique_ptr move

Zur Zeit habe ich einen Code wie diese

std::unique_ptr<SyncToken> DataManager::borrowSyncToken() 
{ 
    std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex); 
    return std::move(syncToken); 
} 

Ich frage mich, ob es eine elegantere Art und Weise ist, wie einfach erklärt:

std::atomic<std::unique_ptr<SyncToken>> syncToken; 

und die Notwendigkeit von Mutex zu vermeiden. Oder vielleicht muss ich mich gar nicht um das Schloss kümmern und std :: move ist schon atomar?

Nach Forschung habe ich bisher scheint es mir:

  • die std :: sich bewegen, ist nicht atomar und braucht eine Synchronisation um ansonsten 2 Threads meine Methode aufrufen gleichzeitig können bis zu 2 Kopien enden von einigen undefinierten Zeigern.
  • die std :: atomare deklaration kompiliert für mich, aber ich weiß nicht, wie man es initialisieren und und machen Sie den Umzug.

Antwort

2

Nein, das ist nicht möglich.

Der Wert T, den Sie an std::atomic übergeben, muss trivial kopierbar sein, was std::unique_ptr nicht ist. Operationen wie std::atomic::load oder std::atomic::store nehmen T-Objekte nach Wert.

Packen etwas in einem std::atomic macht auch keine Operationen aus dem Wert atomare.

Wenn Sie std::unique_ptr in einem atomaren Kontext verwenden, müssen Sie darüber nachdenken, dass Sie Probleme beim Verwalten von Ressourcen haben könnten. Sie wissen nie, wie viele Threads immer noch auf Ihre Daten verweisen, dieses Problem kann mit einer std::shared_ptr gelöst werden, die atomare Referenzzählung verwendet. (Sie müssen überprüfen, ob es wirklich atomar ist, indem Sie die std::atomic_is_lock_free Funktion verwenden.)

Eine Sache, die ich auch stolperte, als ich in Ihrem Code sah, ist die Absicht der borrowSyncToken Funktion. Es heißt borgen, aber Sie übergeben das Eigentum des Tokens an den Aufrufer durch Ausziehen der std::unique_ptr, wie wird der Besitz zurückgegeben und was andere Threads erhalten, wenn der DataManager derzeit nicht das Token besitzt?

+0

Danke für die Antwort und Diskussion der std :: shared_ptr. Für die Absicht: der Code ist vereinfacht, aber ich denke, auch so würde es nullptr zu späteren Threads zurückgeben, so dass ein Anrufer herausfinden kann, dass das Token nicht verfügbar ist. Problem gelöst hier werde ich in einem anderen Kommentar erklären. –

+0

Clients führen zwei Arten von Operationen mit DataManager durch: Lesen, Schreiben. Nur ein Client kann in der Zeit schreiben. ** Clients sind keine Threads ** - manchmal ja, manchmal kann ein Hintergrund-Job für den Client gestartet werden. Lesen/Schreiben bedeutet keine einfache Operation, sondern folgt einem komplexen Kommunikationsprotokoll zwischen DataManager und Client. Die Clientanforderungen müssen nicht unbedingt blockiert werden, bis Token verfügbar sind, aber manchmal werden sie aktiv abgelehnt. Um mich im Chaos zu orientieren, habe ich diesen SyncToken vorgeschlagen - der Schreiber muss SyncToken ausleihen und returnSyncToken (unique_ptr ) aufrufen, wenn er fertig ist. –