2016-08-08 1 views
0

ich habe Timer in meiner app, während Callback seine Funktion jedes 100MMS mit:C++ 11: Wie von Vektorschleife aktualisiert zu verhindern, während ohne Sperren Iterieren

timer_ptr new_timer = lib::make_shared<lib::asio::steady_timer> 

jetzt in Seiten diese Schleife i-Schleife haben, die iterieren Vector und Aktualisierungen für seine Mitglieder.

//copy the members which are relevant in this point in time 
     con_list m_connectionsLocalTmp = m_global_connections; 
     for (const auto it : m_connectionsLocalTmp) 
     { 
      ... 
      ... 
     } 

Der m_global_connections Vektor in der Anwendung keiner gefüllt werden stoppen
so jeder Timer-Rückruf i die Elemente kopieren, die zu diesem Zeitpunkt relevant sind, ich weiß, es ist nicht effizient, aber ich fand keinen besseren Weg, , das Problem ist was passiert, wenn der Timer erneut aufgerufen und die Schleife nicht beendet ist, sondern es aus

con_list m_connectionsLocalTmp = m_global_connections; 

und jetzt Looping es neue Reihe von Elementen aktualisiert.
Wie kann ich diese Logik im Callback bestellen?

Antwort

1

Sie müssen entweder mit einem Mutex oder einem Spinlock basierend auf einer atomaren Variablen sperren. Eine bessere Technik wäre, zwei Vektoren zu haben und sie entsprechend zu tauschen. In diesem Fall verwende ich einfach einen Mutex zur Vereinfachung.

con_list m_connectionsLocalTmp; 
    //copy the members which are relevant in this point in time 
    { 
     std::lock_guard<std::mutex> lock(g_i_mutex); 
     while(!connectionsLocalTmp.empty()){ } 
     std::swap(connectionsLocalTmp, m_global_connections); 
    } 
    for (const auto it : m_connectionsLocalTmp) 
    { 
     ... 
     ... 
    } 
+0

Warum ist der Austausch besser, dann einfach Vektor in Vektor kopieren? – user63898

+0

auch ich muss die m_global_connections beibehalten, wie es ist, wie es das Verbindungsrepository der App – user63898

+0

Die 'Swap' ist besser, da es zwei Zeiger austauscht. Die Dokumentation besagt: "ruft keine Vorgänge zum Verschieben, Kopieren oder Austauschen einzelner Elemente auf." –

1

Wie @dau_sama heißt Sie eine Sperre von einem mutex benötigen. Allerdings würde ich die integrierte Spezialisierung von swap verwenden.

Hacking @dau_sama Beispiel:

con_list m_connectionsLocalTmp; 
//copy the members which are relevant in this point in time 
{ 
    std::lock_guard<std::mutex> lock(g_i_mutex); 
    while(!connectionsLocalTmp.empty()){ } 
    m_global_connections.swap(connectionsLocalTmp); 
} 
for (const auto it : m_connectionsLocalTmp) 
{ 
    // ... 
} 

Allerdings würde ich nicht eine native Vektor für diesen Einsatz aber einen queue Behälteradapter und condition_variable auf Daten warten. Dies löscht den Austausch, die Abfrageschleife und verarbeitet die Daten so, wie sie erscheinen.

+0

Warum würden Sie Warteschlange und nicht Vektor verwenden? und warum condition_variable? – user63898

+0

auch ich muss die m_global_connections behalten wie es ist, wie es das Verbindungsrepository der App – user63898

+0

Es ist mehr eine Frage der Semantik. Ich sehe eingehende Daten als Stream und eine natürlichere Sichtweise, die eine Warteschlange darstellt. Während alle 100ms abgefragt und alles verarbeitet wird, was in den letzten Zehntelsekunden aufgetaucht ist, habe ich das Gefühl, dass die Verarbeitung von Daten eleganter ist. Ich arbeite auch in einer Umgebung, in der 100ms eine lange Zeit sind! –

Verwandte Themen