2012-06-26 5 views
5

sich das folgende Szenario:globale Variable in Namensraum - Werte unterscheiden sich in Threads

  • 2 verschiedene Netzwerk-Ports über boost::asio jedes in einem eigenen Thread
  • 1-Port Daten empfangen und verarbeitet - class DataConnection in einen umhüllten std::thread
  • 1-Port-Statistiken für das Senden von class StatConnection auch in einem

std::thread gewickelt für Zählen Verbindungen (und andere kleine Datenstücke) war meine Idee, eine static Variable innerhalb einer namespace wie zu verwenden: Dies funktioniert gut für die DataConnection Klasse

#include <atomic> 

namespace app { 
namespace status { 
    static std::atomic<long> counter = 0; 
} 
} 

. Hier inkrementiere ich counter im c'tor und sehe die Wertschritte.

Aber counter in meiner StatConnection Klasse ist immer 0

Warum kann das geschehen?

Ich habe einige Alternativen ausprobiert:

  • std::atomic<long> für static volatile long Austausch: Hat einen Unterschied nicht gemacht.
  • mit dem Namespace ohne static Schlüsselwort.

Dann bekam ich Linkerfehler:

multiple definition of `app::status::searchtime' 
./src/status/Status.o:/[...]/include/status/Status.hpp:16: first defined here 
[...] 

Warum also ist der Wert von count unterschiedlich zwischen Threads?

+0

Huh? Statisches Mitglied des Namespace? Warum nicht nur statisches Mitglied der Klasse? – Griwes

+0

Die Klasse existiert nur für kurze Zeit und die boost :: asio-bezogenen Klassen werden n-mal über std :: thread gestartet. Also habe ich gedacht, es in einen Namensraum zu setzen. Aber ein statisches Mitglied könnte das Problem lösen, das ich untersuchen werde. Ich bin mir immer noch nicht sicher, warum der Namespace-Ansatz nicht funktioniert hat. –

Antwort

9

static in Namespacebereich führt interne Bindung, so dass jede Übersetzungseinheit wird eine eigene Kopie von counter – ziemlich das Gegenteil von dem, was Sie wirklich wollen!

Verwenden extern stattdessen im Header:

//foo.h: 
#include <atomic> 

namespace app { 
    namespace status { 
     extern std::atomic<long> counter; 
    } 
} 

definieren, dann wird die Variable in einer Übersetzungseinheit:

//foo.cpp: 
#include "foo.h" 

namespace app { 
    namespace status { 
     std::atomic<long> counter{0L}; 
    } 
} 
+1

um es mit 'std :: atomic ' 'Ich musste in' foo.cpp' schreiben: 'std :: atomic counter (0);' –

+0

@emteh: Ah, ich wusste nicht, ob der Konstruktor war explizit oder nicht. Ich werde bearbeiten, danke. – ildjarn