Skip to content

Commit

Permalink
Fix initialization order problem
Browse files Browse the repository at this point in the history
C++ standart doesn't guarantee the order of initialization for static members in different modules. So, some modules may try to use non-initialized data in the non-initialized module and get an error.
Let's fix this problem using nifty-counter technique.
  • Loading branch information
FreeZoneMods committed Nov 10, 2018
1 parent 83a67af commit fbb86ef
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/utils/xrSE_Factory/ai_space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,35 @@
#include "xrScriptEngine/script_engine.hpp"
#include "xrServerEntities/object_factory.h"

static CAI_Space g_ai_space;
// Nifty counter required to solve initilization order problem
// Please, do NOT initialize this static members directly, it breaks the initialization logic
// And yes, according to the standard ($3.6.2/1): "Objects with static storage duration (3.7.1) shall be
// zero-initialized (8.5) before any other initialization takes place" So, it must be automatically
// initialized with zeros before executing the constructor
static CAI_Space* s_ai_space;
static u32 s_nifty_counter;

SAI_Space_Initializer::SAI_Space_Initializer()
{
if (s_nifty_counter++ == 0)
{
s_ai_space = new CAI_Space();
}
}

SAI_Space_Initializer::~SAI_Space_Initializer()
{
if (--s_nifty_counter == 0)
{
xr_delete(s_ai_space);
}
}

CAI_Space& CAI_Space::GetInstance()
{
auto& instance = g_ai_space;
VERIFY(s_ai_space);

auto& instance = *s_ai_space;
if (!instance.m_inited)
{
instance.init();
Expand Down
8 changes: 8 additions & 0 deletions src/utils/xrSE_Factory/ai_space.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ class CAI_Space
bool Unsubscribe(CEventNotifierCallback::CID cid, EEventID event_id) { return true; }
};

// Static initializer for every translation unit
// Need to avoid static initilization order problem
static struct SAI_Space_Initializer
{
SAI_Space_Initializer();
~SAI_Space_Initializer();
} s_AISpaceInitializer;

IC CAI_Space& ai();

#include "ai_space_inline.h"
28 changes: 26 additions & 2 deletions src/xrGame/ai_space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,35 @@
#include "moving_objects.h"
#include "doors_manager.h"

static CAI_Space g_ai_space;
// Nifty counter required to solve initilization order problem
// Please, do NOT initialize this static members directly, it breaks the initialization logic
// And yes, according to the standard ($3.6.2/1): "Objects with static storage duration (3.7.1) shall be
// zero-initialized (8.5) before any other initialization takes place" So, it must be automatically
// initialized with zeros before executing the constructor
static CAI_Space* s_ai_space;
static u32 s_nifty_counter;

SAI_Space_Initializer::SAI_Space_Initializer()
{
if (s_nifty_counter++ == 0)
{
s_ai_space = new CAI_Space();
}
}

SAI_Space_Initializer::~SAI_Space_Initializer()
{
if (--s_nifty_counter == 0)
{
xr_delete(s_ai_space);
}
}

CAI_Space& CAI_Space::GetInstance()
{
auto& instance = g_ai_space;
VERIFY(s_ai_space);

auto& instance = *s_ai_space;
if (!instance.m_inited)
{
instance.init();
Expand Down
8 changes: 8 additions & 0 deletions src/xrGame/ai_space.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ class CAI_Space : public AISpaceBase
IC doors::manager& doors() const;
};

// Static initializer for every translation unit
// Need to avoid static initilization order problem
static struct SAI_Space_Initializer
{
SAI_Space_Initializer();
~SAI_Space_Initializer();
} s_AISpaceInitializer;

IC CAI_Space& ai();

#include "ai_space_inline.h"

0 comments on commit fbb86ef

Please sign in to comment.