From 9ff2fb4fef0b0b3bb4317e1a88730f718baf3e2a Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:41:08 -0500 Subject: [PATCH] refactor: switch to thread_local in Chunk, PistonBaseTile, TheEndPortalTile, Compression --- Minecraft.Client/Rendering/Chunk.cpp | 13 +++----- Minecraft.Client/Rendering/Chunk.h | 4 +-- Minecraft.World/Blocks/PistonBaseTile.cpp | 37 ++------------------- Minecraft.World/Blocks/PistonBaseTile.h | 2 ++ Minecraft.World/Blocks/TheEndPortalTile.cpp | 37 ++------------------- Minecraft.World/Blocks/TheEndPortalTile.h | 13 ++------ Minecraft.World/IO/Streams/Compression.cpp | 22 +++++------- Minecraft.World/IO/Streams/Compression.h | 4 +-- 8 files changed, 29 insertions(+), 103 deletions(-) diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp index ccc786872..05a2b2d55 100644 --- a/Minecraft.Client/Rendering/Chunk.cpp +++ b/Minecraft.Client/Rendering/Chunk.cpp @@ -20,21 +20,18 @@ int Chunk::updates = 0; #ifdef _LARGE_WORLDS -unsigned int Chunk::tlsIdx = TlsAlloc(); +thread_local uint8_t* Chunk::m_threadTileIds = nullptr; void Chunk::CreateNewThreadStorage() { - unsigned char* tileIds = new unsigned char[16 * 16 * Level::maxBuildHeight]; - TlsSetValue(tlsIdx, tileIds); + m_threadTileIds = new unsigned char[16 * 16 * Level::maxBuildHeight]; } void Chunk::ReleaseThreadStorage() { - unsigned char* tileIds = (unsigned char*)TlsGetValue(tlsIdx); - delete tileIds; + delete m_threadTileIds; } -unsigned char* Chunk::GetTileIdsStorage() { - unsigned char* tileIds = (unsigned char*)TlsGetValue(tlsIdx); - return tileIds; +uint8_t* Chunk::GetTileIdsStorage() { + return m_threadTileIds; } #else // 4J Stu - Don't want this when multi-threaded diff --git a/Minecraft.Client/Rendering/Chunk.h b/Minecraft.Client/Rendering/Chunk.h index 23d5ef532..7ba3c55fa 100644 --- a/Minecraft.Client/Rendering/Chunk.h +++ b/Minecraft.Client/Rendering/Chunk.h @@ -30,12 +30,12 @@ private: #ifndef _LARGE_WORLDS static Tesselator* t; #else - static unsigned int tlsIdx; + static thread_local uint8_t* m_threadTileIds; public: static void CreateNewThreadStorage(); static void ReleaseThreadStorage(); - static unsigned char* GetTileIdsStorage(); + static uint8_t* GetTileIdsStorage(); #endif public: diff --git a/Minecraft.World/Blocks/PistonBaseTile.cpp b/Minecraft.World/Blocks/PistonBaseTile.cpp index d75a157ad..686c759c9 100644 --- a/Minecraft.World/Blocks/PistonBaseTile.cpp +++ b/Minecraft.World/Blocks/PistonBaseTile.cpp @@ -20,37 +20,7 @@ const std::wstring PistonBaseTile::INSIDE_TEX = L"piston_inner_top"; const float PistonBaseTile::PLATFORM_THICKNESS = 4.0f; -namespace { -#if defined(_WIN32) -inline void* PistonTlsGetValue(PistonBaseTile::TlsKey key) { - return TlsGetValue(key); -} - -inline void PistonTlsSetValue(PistonBaseTile::TlsKey key, void* value) { - TlsSetValue(key, value); -} -#else -pthread_key_t CreatePistonTlsKey() { - pthread_key_t key; - pthread_key_create(&key, NULL); - return key; -} - -inline void* PistonTlsGetValue(pthread_key_t key) { - return pthread_getspecific(key); -} - -inline void PistonTlsSetValue(pthread_key_t key, void* value) { - pthread_setspecific(key, value); -} -#endif -} // namespace - -#if defined(_WIN32) -PistonBaseTile::TlsKey PistonBaseTile::tlsIdx = TlsAlloc(); -#else -PistonBaseTile::TlsKey PistonBaseTile::tlsIdx = CreatePistonTlsKey(); -#endif +thread_local bool PistonBaseTile::m_threadIgnoreUpdate = false; // 4J - NOTE - this ignoreUpdate stuff has been removed from the java version, // but I'm not currently sure how the java version does without it... there must @@ -62,12 +32,11 @@ PistonBaseTile::TlsKey PistonBaseTile::tlsIdx = CreatePistonTlsKey(); // 4J - ignoreUpdate is a static in java, implementing as TLS here to make // thread safe bool PistonBaseTile::ignoreUpdate() { - return PistonTlsGetValue(tlsIdx) != NULL; + return m_threadIgnoreUpdate; } void PistonBaseTile::ignoreUpdate(bool set) { - PistonTlsSetValue( - tlsIdx, reinterpret_cast(static_cast(set ? 1 : 0))); + m_threadIgnoreUpdate = set; } PistonBaseTile::PistonBaseTile(int id, bool isSticky) diff --git a/Minecraft.World/Blocks/PistonBaseTile.h b/Minecraft.World/Blocks/PistonBaseTile.h index eb038e6ae..d31527624 100644 --- a/Minecraft.World/Blocks/PistonBaseTile.h +++ b/Minecraft.World/Blocks/PistonBaseTile.h @@ -35,6 +35,8 @@ private: Icon* iconBack; Icon* iconPlatform; + static thread_local bool m_threadIgnoreUpdate; + static TlsKey tlsIdx; // 4J - was just a static but implemented with TLS for our version static bool ignoreUpdate(); diff --git a/Minecraft.World/Blocks/TheEndPortalTile.cpp b/Minecraft.World/Blocks/TheEndPortalTile.cpp index a2fa0a5ad..a8181c39b 100644 --- a/Minecraft.World/Blocks/TheEndPortalTile.cpp +++ b/Minecraft.World/Blocks/TheEndPortalTile.cpp @@ -9,47 +9,16 @@ #include "../Headers/net.minecraft.world.h" #include -namespace { -#if defined(_WIN32) -inline void* TheEndPortalTlsGetValue(TheEndPortal::TlsKey key) { - return TlsGetValue(key); -} - -inline void TheEndPortalTlsSetValue(TheEndPortal::TlsKey key, void* value) { - TlsSetValue(key, value); -} -#else -pthread_key_t CreateTheEndPortalTlsKey() { - pthread_key_t key; - pthread_key_create(&key, NULL); - return key; -} - -inline void* TheEndPortalTlsGetValue(pthread_key_t key) { - return pthread_getspecific(key); -} - -inline void TheEndPortalTlsSetValue(pthread_key_t key, void* value) { - pthread_setspecific(key, value); -} -#endif -} // namespace - -#if defined(_WIN32) -TheEndPortal::TlsKey TheEndPortal::tlsIdx = TlsAlloc(); -#else -TheEndPortal::TlsKey TheEndPortal::tlsIdx = CreateTheEndPortalTlsKey(); -#endif +thread_local bool TheEndPortal::m_threadAllowAnywhere = false; // 4J - allowAnywhere is a static in java, implementing as TLS here to make // thread safe bool TheEndPortal::allowAnywhere() { - return TheEndPortalTlsGetValue(tlsIdx) != NULL; + return m_threadAllowAnywhere; } void TheEndPortal::allowAnywhere(bool set) { - TheEndPortalTlsSetValue( - tlsIdx, reinterpret_cast(static_cast(set ? 1 : 0))); + m_threadAllowAnywhere = set; } TheEndPortal::TheEndPortal(int id, Material* material) diff --git a/Minecraft.World/Blocks/TheEndPortalTile.h b/Minecraft.World/Blocks/TheEndPortalTile.h index 6e3531777..3e6e224be 100644 --- a/Minecraft.World/Blocks/TheEndPortalTile.h +++ b/Minecraft.World/Blocks/TheEndPortalTile.h @@ -3,20 +3,10 @@ #include "BaseEntityTile.h" #include -#if !defined(_WIN32) -#include -#endif - class IconRegister; class TheEndPortal : public BaseEntityTile { public: -#if defined(_WIN32) - using TlsKey = std::uint32_t; -#else - using TlsKey = pthread_key_t; -#endif - static TlsKey tlsIdx; // 4J - was just a static but implemented with TLS for our version static bool allowAnywhere(); static void allowAnywhere(bool set); @@ -43,4 +33,7 @@ public: virtual void onPlace(Level* level, int x, int y, int z); virtual int cloneTileId(Level* level, int x, int y, int z); void registerIcons(IconRegister* iconRegister); + +private: + static thread_local bool m_threadAllowAnywhere; }; \ No newline at end of file diff --git a/Minecraft.World/IO/Streams/Compression.cpp b/Minecraft.World/IO/Streams/Compression.cpp index 543f05296..edc2f068a 100644 --- a/Minecraft.World/IO/Streams/Compression.cpp +++ b/Minecraft.World/IO/Streams/Compression.cpp @@ -17,8 +17,8 @@ #include "../../../Minecraft.Client/Platform/PS3/PS3Extras/EdgeZLib.h" #endif //__PS3__ -unsigned int Compression::tlsIdx = 0; -Compression::ThreadStorage* Compression::tlsDefault = NULL; +thread_local Compression::ThreadStorage* Compression::m_threadCompression = nullptr; +Compression::ThreadStorage* Compression::m_threadCompressionDefault = nullptr; Compression::ThreadStorage::ThreadStorage() { compression = new Compression(); } @@ -26,28 +26,24 @@ Compression::ThreadStorage::~ThreadStorage() { delete compression; } void Compression::CreateNewThreadStorage() { ThreadStorage* tls = new ThreadStorage(); - if (tlsDefault == nullptr) { - pthread_key_create(&tlsIdx, nullptr); - tlsDefault = tls; + if (m_threadCompressionDefault == nullptr) { + m_threadCompressionDefault = tls; } - pthread_setspecific(tlsIdx, tls); + m_threadCompression = tls; } void Compression::UseDefaultThreadStorage() { - pthread_setspecific(tlsIdx, tlsDefault); + m_threadCompression = m_threadCompressionDefault; } void Compression::ReleaseThreadStorage() { - ThreadStorage* tls = - (ThreadStorage*)pthread_getspecific(tlsIdx); // POSIX equivalent - if (tls != tlsDefault) { - delete tls; + if (m_threadCompression != m_threadCompressionDefault) { + delete m_threadCompression; } } Compression* Compression::getCompression() { - ThreadStorage* tls = (ThreadStorage*)pthread_getspecific(tlsIdx); - return tls->compression; + return m_threadCompression->compression; } HRESULT Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, diff --git a/Minecraft.World/IO/Streams/Compression.h b/Minecraft.World/IO/Streams/Compression.h index 1b2529231..a8410a671 100644 --- a/Minecraft.World/IO/Streams/Compression.h +++ b/Minecraft.World/IO/Streams/Compression.h @@ -25,8 +25,8 @@ private: ThreadStorage(); ~ThreadStorage(); }; - static unsigned int tlsIdx; - static ThreadStorage* tlsDefault; + static thread_local ThreadStorage* m_threadCompression; + static ThreadStorage* m_threadCompressionDefault; public: // Each new thread that needs to use Compression will need to call one of