diff --git a/src/FireDomain.cpp b/src/FireDomain.cpp index 240c5af..269afcd 100644 --- a/src/FireDomain.cpp +++ b/src/FireDomain.cpp @@ -27,7 +27,7 @@ // On fait plus de chaines.... // Static variables - long ForeFireAtom::instanceNRCount = 0; + std::atomic ForeFireAtom::instanceNRCount{0}; const double FireDomain::endChain = -1.; const double FireDomain::endCom = -10.; diff --git a/src/ForeFireAtom.h b/src/ForeFireAtom.h index f8b56ca..378df6f 100644 --- a/src/ForeFireAtom.h +++ b/src/ForeFireAtom.h @@ -11,6 +11,8 @@ #include "include/Futils.h" +#include + using namespace std; namespace libforefire{ @@ -33,7 +35,13 @@ namespace libforefire{ class ForeFireAtom { private: - static long instanceNRCount; /*!< Instance Count */ + /*! \brief Instance count, the source of every atom's id. + * + * Atomic because objects are created from more than one thread once the + * GIL is out of the way, and a plain `++` there is a data race that can + * hand the same id to two atoms. + */ + static std::atomic instanceNRCount; double time; /*!< current time of the object */ double updateTime; /*!< next update time */ @@ -103,7 +111,10 @@ class ForeFireAtom { return getIDfromLongs((long) did/domainMult(),(long) did%domainMult()); } void getNewID(const long& domainId){ - numID = getIDfromLongs(domainId,instanceNRCount++); + // relaxed: ids only have to be distinct, not ordered against other + // memory operations. + numID = getIDfromLongs(domainId, + instanceNRCount.fetch_add(1, std::memory_order_relaxed)); } /*! \brief Pure virtual function for inpus */ diff --git a/src/SimulationParameters.cpp b/src/SimulationParameters.cpp index d01a3be..024e432 100644 --- a/src/SimulationParameters.cpp +++ b/src/SimulationParameters.cpp @@ -17,8 +17,6 @@ namespace libforefire { -SimulationParameters* SimulationParameters::instance = 0; - string SimulationParameters::undefined = "1234567890"; double SimulationParameters::doubleUndefined = 1234567890.; int SimulationParameters::intUndefined = 1234567890; @@ -26,7 +24,13 @@ size_t SimulationParameters::sizeUndefined = 1234567890; SimulationParameters* SimulationParameters::GetInstance(){ - if ( instance == 0 ) instance = new SimulationParameters; + // A function-local static: C++11 onwards guarantees its initialisation + // runs exactly once even if several threads arrive here together. The + // previous `if (instance == 0) instance = new ...` let two threads both + // see null and both construct, leaving them with different parameter + // objects. Never deleted, matching the previous behaviour; the parameters + // live for the whole process. + static SimulationParameters* const instance = new SimulationParameters(); return instance; } diff --git a/src/SimulationParameters.h b/src/SimulationParameters.h index 7be1cb4..06551d7 100644 --- a/src/SimulationParameters.h +++ b/src/SimulationParameters.h @@ -18,8 +18,6 @@ namespace libforefire { class SimulationParameters { - static SimulationParameters* instance; /*!< Singleton-type class */ - /*! values for undefined parameters */ static string undefined; static double doubleUndefined;