refactor: use function-local statics for platform accessors to dodge SIOF

This commit is contained in:
MatthewBeshay 2026-04-08 20:22:40 +10:00
parent 60410f59bf
commit b032e2a3a0
10 changed files with 110 additions and 22 deletions

View file

@ -1,3 +1,18 @@
#pragma once
#include "IPlatformFilesystem.h"
extern IPlatformFilesystem& PlatformFilesystem;
// Function accessor backed by a function-local static (Meyers singleton).
// Avoids the static-initialization-order fiasco that the previous
// `extern IPlatformFilesystem& PlatformFilesystem;` form had: anything reading PlatformFilesystem
// during another translation unit's static init was UB.
//
// The macro lets the existing call sites keep writing `PlatformFilesystem.foo()`
// without each call site having to add the `()`. The expansion is just
// a call to a function returning a reference, so codegen is unchanged
// once inlined.
namespace platform_internal {
IPlatformFilesystem& PlatformFilesystem_get();
}
#define PlatformFilesystem (::platform_internal::PlatformFilesystem_get())

View file

@ -6,8 +6,12 @@
#include <unistd.h>
#endif
StdFilesystem std_filesystem_instance;
IPlatformFilesystem& PlatformFilesystem = std_filesystem_instance;
namespace platform_internal {
IPlatformFilesystem& PlatformFilesystem_get() {
static StdFilesystem instance;
return instance;
}
}
IPlatformFilesystem::ReadResult StdFilesystem::readFile(const std::filesystem::path& path,
void* buffer, std::size_t capacity) {

View file

@ -1,3 +1,18 @@
#pragma once
#include "IPlatformInput.h"
extern IPlatformInput& PlatformInput;
// Function accessor backed by a function-local static (Meyers singleton).
// Avoids the static-initialization-order fiasco that the previous
// `extern IPlatformInput& PlatformInput;` form had: anything reading PlatformInput
// during another translation unit's static init was UB.
//
// The macro lets the existing call sites keep writing `PlatformInput.foo()`
// without each call site having to add the `()`. The expansion is just
// a call to a function returning a reference, so codegen is unchanged
// once inlined.
namespace platform_internal {
IPlatformInput& PlatformInput_get();
}
#define PlatformInput (::platform_internal::PlatformInput_get())

View file

@ -20,8 +20,12 @@
#include "../InputConstants.h"
#include "../../PlatformTypes.h"
SDL2Input sdl2_input_instance;
IPlatformInput& PlatformInput = sdl2_input_instance;
namespace platform_internal {
IPlatformInput& PlatformInput_get() {
static SDL2Input instance;
return instance;
}
}
static const int KEY_COUNT = SDL_NUM_SCANCODES;
static const int BTN_COUNT = SDL_CONTROLLER_BUTTON_MAX;

View file

@ -1,4 +1,18 @@
#include "IPlatformProfile.h"
#include "ProfileConstants.h"
#pragma once
extern IPlatformProfile& PlatformProfile;
#include "IPlatformProfile.h"
// Function accessor backed by a function-local static (Meyers singleton).
// Avoids the static-initialization-order fiasco that the previous
// `extern IPlatformProfile& PlatformProfile;` form had: anything reading PlatformProfile
// during another translation unit's static init was UB.
//
// The macro lets the existing call sites keep writing `PlatformProfile.foo()`
// without each call site having to add the `()`. The expansion is just
// a call to a function returning a reference, so codegen is unchanged
// once inlined.
namespace platform_internal {
IPlatformProfile& PlatformProfile_get();
}
#define PlatformProfile (::platform_internal::PlatformProfile_get())

View file

@ -7,8 +7,12 @@
#include "../ProfileConstants.h"
#include "input/input.h"
StubProfile stub_profile_instance;
IPlatformProfile& PlatformProfile = stub_profile_instance;
namespace platform_internal {
IPlatformProfile& PlatformProfile_get() {
static StubProfile instance;
return instance;
}
}
namespace {
constexpr PlayerUID kFakeXuidBase = 0xe000d45248242f2eULL;

View file

@ -1,5 +1,6 @@
#include "GLRenderer.h"
#include "renderer/renderer.h"
#include "PlatformTypes.h"
#include "SDL.h"
#include "SDL_error.h"
@ -54,8 +55,12 @@
#include <utility>
#include <vector>
GLRenderer gl_renderer_instance;
IPlatformRenderer& PlatformRenderer = gl_renderer_instance;
namespace platform_internal {
IPlatformRenderer& PlatformRenderer_get() {
static GLRenderer instance;
return instance;
}
}
// MARK: Shaders

View file

@ -2,9 +2,17 @@
#include "IPlatformRenderer.h"
// Defined in the linked renderer backend (currently
// platform/renderer/gl/GLRenderer.cpp). The legacy gl* macro shim used
// by older rendering call sites lives in
// platform/renderer/gl/gl_compat.h, which is brought in via
// platform/stubs.h on linux.
extern IPlatformRenderer& PlatformRenderer;
// Function accessor backed by a function-local static (Meyers singleton).
// Avoids the static-initialization-order fiasco that the previous
// `extern IPlatformRenderer& PlatformRenderer;` form had: anything reading PlatformRenderer
// during another translation unit's static init was UB.
//
// The macro lets the existing call sites keep writing `PlatformRenderer.foo()`
// without each call site having to add the `()`. The expansion is just
// a call to a function returning a reference, so codegen is unchanged
// once inlined.
namespace platform_internal {
IPlatformRenderer& PlatformRenderer_get();
}
#define PlatformRenderer (::platform_internal::PlatformRenderer_get())

View file

@ -1,3 +1,18 @@
#pragma once
#include "IPlatformStorage.h"
extern IPlatformStorage& PlatformStorage;
// Function accessor backed by a function-local static (Meyers singleton).
// Avoids the static-initialization-order fiasco that the previous
// `extern IPlatformStorage& PlatformStorage;` form had: anything reading PlatformStorage
// during another translation unit's static init was UB.
//
// The macro lets the existing call sites keep writing `PlatformStorage.foo()`
// without each call site having to add the `()`. The expansion is just
// a call to a function returning a reference, so codegen is unchanged
// once inlined.
namespace platform_internal {
IPlatformStorage& PlatformStorage_get();
}
#define PlatformStorage (::platform_internal::PlatformStorage_get())

View file

@ -6,8 +6,12 @@
#include <string>
#include <vector>
StubStorage stub_storage_instance;
IPlatformStorage& PlatformStorage = stub_storage_instance;
namespace platform_internal {
IPlatformStorage& PlatformStorage_get() {
static StubStorage instance;
return instance;
}
}
static XMARKETPLACE_CONTENTOFFER_INFO s_dummyOffer = {};
static XCONTENT_DATA s_dummyContentData = {};