Replace usage of remaining boost::unordered containers with std

Replace LLUUID and LLMaterialID container hashing functions with more collision resistant versions
Utilize boost::hash_combine for TEMaterialPair to generate good hash distribution
Generalize is_in_map and get_if_there for usage with all mapped types
This commit is contained in:
Rye
2026-01-21 22:07:08 +02:00
committed by Andrey Kleshchev
parent aad49bd414
commit 76a80b6787
14 changed files with 97 additions and 88 deletions
+2 -2
View File
@@ -38,9 +38,9 @@
#include "llsingleton.h"
#include <boost/call_traits.hpp>
#include <boost/utility/value_init.hpp>
#include <boost/unordered_map.hpp>
#include <boost/signals2/signal.hpp>
#include <unordered_map>
#include <type_traits>
// Forward declare the user template, since we want to be able to point to it
@@ -86,7 +86,7 @@ class LLPounceableQueueSingleton:
// instance will call on the SAME LLPounceableQueueSingleton instance --
// given how class statics work. We must keep a separate queue for each
// LLPounceable instance. Use a hash map for that.
typedef boost::unordered_map<owner_ptr, signal_t> map_t;
typedef std::unordered_map<owner_ptr, signal_t> map_t;
public:
// Disambiguate queues belonging to different LLPounceables.
+2 -2
View File
@@ -25,10 +25,10 @@
#ifndef LLSINGLETON_H
#define LLSINGLETON_H
#include <boost/unordered_set.hpp>
#include <initializer_list>
#include <list>
#include <typeinfo>
#include <unordered_set>
#include <vector>
#include "mutex.h"
#include "lockstatic.h"
@@ -61,7 +61,7 @@ private:
static vec_t dep_sort();
// we directly depend on these other LLSingletons
typedef boost::unordered_set<LLSingletonBase*> set_t;
typedef std::unordered_set<LLSingletonBase*> set_t;
set_t mDepends;
protected:
+3 -2
View File
@@ -29,9 +29,10 @@
#define LL_STATIC_STRING_TABLE_H
#include "lldefs.h"
#include <boost/unordered_map.hpp>
#include "llstl.h"
#include <unordered_map>
class LLStaticHashedString
{
public:
@@ -74,7 +75,7 @@ struct LLStaticStringHasher
template< typename MappedObject >
class LL_COMMON_API LLStaticStringTable
: public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
: public std::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
{
};
+7 -11
View File
@@ -229,12 +229,10 @@ void delete_and_clear_array(T*& ptr)
template <typename T>
inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_type const& key)
{
// Typedef here avoids warnings because of new c++ naming rules.
typedef typename T::const_iterator map_iter;
map_iter iter = inmap.find(key);
auto iter = inmap.find(key);
if(iter == inmap.end())
{
return NULL;
return nullptr;
}
else
{
@@ -243,8 +241,8 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty
};
// helper function which returns true if key is in inmap.
template <typename K, typename T>
inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
template <typename T>
inline bool is_in_map(const T& inmap, typename T::key_type const& key)
{
if(inmap.find(key) == inmap.end())
{
@@ -260,12 +258,10 @@ inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
// To replace LLSkipMap getIfThere, use:
// get_if_there(map, key, 0)
// WARNING: Make sure default_value (generally 0) is not a valid map entry!
template <typename K, typename T>
inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
template <typename T>
inline typename T::mapped_type get_if_there(const T& inmap, typename T::key_type const& key, typename T::mapped_type default_value)
{
// Typedef here avoids warnings because of new c++ naming rules.
typedef typename std::map<K,T>::const_iterator map_iter;
map_iter iter = inmap.find(key);
auto iter = inmap.find(key);
if(iter == inmap.end())
{
return default_value;
+16 -3
View File
@@ -26,6 +26,7 @@
#ifndef LL_LLUUID_H
#define LL_LLUUID_H
#include <functional>
#include <iostream>
#include <set>
#include <vector>
@@ -176,15 +177,27 @@ namespace std
{
inline size_t operator()(const LLUUID& id) const noexcept
{
return (size_t)id.getDigest64();
size_t h = 0;
// Golden ratio hash with avalanche mixing
// Process 8 bytes at a time by manually constructing 64-bit values
// Shift by 31: mixes upper half into lower half for better bit distribution
// Shift by 47: ensures highest bits influence final hash output
for (int i = 0; i < UUID_BYTES; i += 8) {
size_t chunk = (size_t)id.mData[i] | ((size_t)id.mData[i+1] << 8) |
((size_t)id.mData[i+2] << 16) | ((size_t)id.mData[i+3] << 24) |
((size_t)id.mData[i+4] << 32) | ((size_t)id.mData[i+5] << 40) |
((size_t)id.mData[i+6] << 48) | ((size_t)id.mData[i+7] << 56);
h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47);
}
return h;
}
};
}
// For use with boost containers.
// For use with boost::container_hash
inline size_t hash_value(const LLUUID& id) noexcept
{
return (size_t)id.getDigest64();
return std::hash<LLUUID>{}(id);
}
#endif // LL_LLUUID_H
+19 -11
View File
@@ -67,15 +67,11 @@ public:
static const LLMaterialID null;
// Returns a 64 bits digest of the material Id, by XORing its two 64 bits
// long words. HB
inline U64 getDigest64() const
{
U64* tmp = (U64*)mID;
return tmp[0] ^ tmp[1];
}
private:
// definitions follow class
friend std::hash<LLMaterialID>;
friend size_t hash_value(const LLMaterialID&) noexcept;
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const;
@@ -90,15 +86,27 @@ namespace std
{
inline size_t operator()(const LLMaterialID& id) const noexcept
{
return (size_t)id.getDigest64();
size_t h = 0;
// Golden ratio hash with avalanche mixing
// Process 8 bytes at a time by manually constructing 64-bit values
// Shift by 31: mixes upper half into lower half for better bit distribution
// Shift by 47: ensures highest bits influence final hash output
for (int i = 0; i < MATERIAL_ID_SIZE; i += 8) {
size_t chunk = (size_t)id.mID[i] | ((size_t)id.mID[i + 1] << 8) |
((size_t)id.mID[i+2] << 16) | ((size_t)id.mID[i+3] << 24) |
((size_t)id.mID[i+4] << 32) | ((size_t)id.mID[i+5] << 40) |
((size_t)id.mID[i + 6] << 48) | ((size_t)id.mID[i + 7] << 56);
h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47);
}
return h;
}
};
}
// For use with boost containers.
// For use with boost::container_hash
inline size_t hash_value(const LLMaterialID& id) noexcept
{
return (size_t)id.getDigest64();
return std::hash<LLMaterialID>{}(id);
}
#endif // LL_LLMATERIALID_H
+3 -2
View File
@@ -27,13 +27,14 @@
#ifndef LL_LLFONTFREETYPE_H
#define LL_LLFONTFREETYPE_H
#include <boost/unordered_map.hpp>
#include "llpointer.h"
#include "llstl.h"
#include "llimagegl.h"
#include "llfontbitmapcache.h"
#include <unordered_map>
// Hack. FT_Face is just a typedef for a pointer to a struct,
// but there's no simple forward declarations file for FreeType,
// and the main include file is 200K.
@@ -184,7 +185,7 @@ private:
fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
// *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
typedef std::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLFontBitmapCache* mFontBitmapCachep;
+3 -3
View File
@@ -2376,7 +2376,7 @@ void clear_glerror()
//
// Static members
boost::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
std::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default
GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default
@@ -2419,7 +2419,7 @@ void LLGLState::resetTextureStates()
void LLGLState::dumpStates()
{
LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"true":"false") << LL_ENDL;
@@ -2451,7 +2451,7 @@ void LLGLState::checkStates(GLboolean writeAlpha)
//llassert_always(colorMask[2]);
// llassert_always(colorMask[3] == writeAlpha);
for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LLGLenum state = iter->first;
+2 -2
View File
@@ -31,7 +31,7 @@
#include <functional>
#include <string>
#include <boost/unordered_map.hpp>
#include <unordered_map>
#include <list>
#include "llerror.h"
@@ -246,7 +246,7 @@ public:
static void checkStates(GLboolean writeAlpha = GL_TRUE);
protected:
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
static std::unordered_map<LLGLenum, LLGLboolean> sStateMap;
public:
enum { CURRENT_STATE = -2, DISABLED_STATE = 0, ENABLED_STATE = 1 };
+34 -42
View File
@@ -33,9 +33,42 @@
#include "httprequest.h"
#include "httpheaders.h"
#include "httpoptions.h"
#include <boost/container_hash/hash.hpp>
class LLViewerRegion;
// struct for TE-specific material ID query
class TEMaterialPair
{
public:
U32 te;
LLMaterialID materialID;
bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
};
inline bool operator<(const TEMaterialPair& lhs, const TEMaterialPair& rhs)
{
return (lhs.te < rhs.te) ? true : (lhs.materialID < rhs.materialID);
}
// std::hash implementation for TEMaterialPair
namespace std
{
template<>
struct hash<TEMaterialPair>
{
inline size_t operator()(const TEMaterialPair& p) const noexcept
{
// Utilize boost::hash_combine to generate a good hash
size_t seed = 0;
boost::hash_combine(seed, p.te + 1);
boost::hash_combine(seed, p.materialID);
return seed;
}
};
} // namespace std
class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
{
LLSINGLETON(LLMaterialMgr);
@@ -83,29 +116,6 @@ private:
void onRegionRemoved(LLViewerRegion* regionp);
private:
// struct for TE-specific material ID query
class TEMaterialPair
{
public:
U32 te;
LLMaterialID materialID;
bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
};
// definitions follow class
friend std::hash<TEMaterialPair>;
friend size_t hash_value(const TEMaterialPair&) noexcept;
friend inline bool operator<(
const LLMaterialMgr::TEMaterialPair& lhs,
const LLMaterialMgr::TEMaterialPair& rhs)
{
return (lhs.te < rhs.te) ? true :
(lhs.materialID < rhs.materialID);
}
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
@@ -113,7 +123,7 @@ private:
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
typedef std::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
typedef std::set<LLUUID> getall_queue_t;
typedef std::map<LLUUID, F64> getall_pending_map_t;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
@@ -142,23 +152,5 @@ private:
U32 getMaxEntries(const LLViewerRegion* regionp);
};
// std::hash implementation for TEMaterialPair
namespace std
{
template<> struct hash<LLMaterialMgr::TEMaterialPair>
{
inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
};
}
// For use with boost containers.
inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
#endif // LL_LLMATERIALMGR_H
+1 -1
View File
@@ -442,7 +442,7 @@ public:
LLCondition* mSignal;
//map of known mesh headers
typedef boost::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data
typedef std::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
class HeaderRequest : public RequestStats
+1 -1
View File
@@ -223,7 +223,7 @@ namespace LLPerfStats
static void updateMeanFrameTime(U64 tot_frame_time_raw);
// StatsArray is a uint64_t for each possible statistic type.
using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>;
using StatsMap = std::unordered_map<LLUUID, StatsArray, boost::hash<LLUUID>>;
using StatsMap = std::unordered_map<LLUUID, StatsArray>;
using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
+4 -4
View File
@@ -140,7 +140,7 @@
#include "llwindow.h"
#include "llpathfindingmanager.h"
#include "llstartup.h"
#include "boost/unordered_map.hpp"
#include <unordered_map>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/json.hpp>
@@ -153,7 +153,7 @@ using namespace LLAvatarAppearanceDefines;
typedef LLPointer<LLViewerObject> LLViewerObjectPtr;
static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
static std::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
LLVOAvatar* find_avatar_from_object(LLViewerObject* object);
LLVOAvatar* find_avatar_from_object(const LLUUID& object_id);
@@ -2965,7 +2965,7 @@ void handle_object_show_original()
static void init_default_item_label(LLUICtrl* ctrl)
{
const std::string& item_name = ctrl->getName();
boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
if (it == sDefaultItemLabels.end())
{
// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
@@ -2981,7 +2981,7 @@ static void init_default_item_label(LLUICtrl* ctrl)
static LLStringExplicit get_default_item_label(const std::string& item_name)
{
LLStringExplicit res("");
boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
if (it != sDefaultItemLabels.end())
{
res = it->second;
@@ -126,8 +126,6 @@
#include "llfloater.h"
#include <boost/signals2.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/json.hpp>
#include "glm/glm.hpp"