/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
App/util/Name.cpp
185 строк
4 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
#include "stdafx.h" #include "util/name.h" #include "rbx/threadsafe.h" #include "rbx/Debug.h" #include <boost/thread/once.hpp> #include <boost/unordered_map.hpp> using namespace RBX; namespace { struct StrHash : std::unary_function<const char*, std::size_t> { size_t operator()(const char*s) const { size_t h = boost::hash_range(s, s + strlen(s) ); return h; } }; struct StrEqualTo : public std::binary_function<const char*, const char*, bool> { bool operator()(const char* a, const char* b) const { return strcmp(a, b) == 0; } }; } // namespace class Name::NameMap : public boost::unordered_map<const char *, Name*, StrHash, StrEqualTo> { public: ~NameMap(); }; Name::Name(const char* const& name) :str(name) { setOrderIndex(); } Name::NameMap::~NameMap() { NameMap::iterator iter = begin(); while (iter!=end()) { delete iter->second; ++iter; } } ////////////////////////////////////////// // Cumbersome code to ensure that the mutex is initalized // in a thread-safe manner static RBX::mutex& moo2() { static RBX::mutex mutex2; return mutex2; } static void initMoo() { moo2(); } static boost::once_flag mooFlag = BOOST_ONCE_INIT; RBX::mutex& Name::mutex() { boost::call_once(&initMoo, mooFlag); return moo2(); } // //////////////////////////////////////////// Name::NameMap& Name::map() { static NameMap n; return n; } size_t Name::approximateMemoryUsage() { // is this reasonable? return 64 * map().size(); } size_t Name::size() { return map().size(); } static const Name* nullName; static void declareNullName() { nullName = &Name::declare(""); } const Name& Name::getNullName() { static boost::once_flag flag2 = BOOST_ONCE_INIT; boost::call_once(&declareNullName, flag2); return *nullName; } void Name::setOrderIndex() { static std::vector<Name*> ordered; // Go from highest to lowest to keep sort order index comparisons invariant size_t i = ordered.size(); for (; i > 0; --i) { RBXASSERT(ordered[i-1]->str != str); if (str > ordered[i-1]->str) break; ordered[i-1]->sortIndex++; RBXASSERT(ordered[i-1]->sortIndex == i); } this->sortIndex = i; ordered.insert(ordered.begin() + i, this); #ifdef _DEBUG for (size_t j = 0; j < ordered.size(); ++j) RBXASSERT(ordered[j]->sortIndex == j); #endif } const Name& Name::declare(const char* const& sName) { if (sName==NULL) { return getNullName(); } Name* result; { // This scope needs to be closed before calling getNullName or the // mutex will be recursively locked. RBX::mutex::scoped_lock lock(mutex()); const Name& (*thisFunction)(const char* const &) = &RBX::Name::declare; // required due to overload. checkRbxCaller<kCallCheckCallersCode, callCheckSetApiFlag<kNameApiOffset> >(reinterpret_cast<void*>(thisFunction)); NameMap::iterator iter = map().find(sName); if (iter!=map().end()) return *iter->second; Name* name = new Name(sName); map()[name->c_str()] = name; result = name; } RBXASSERT(sName[0]=='\0' || (!result->str.empty() && lookup(sName) != Name::getNullName()) ); return *result; } const Name& Name::lookup(const char* const& sName) { if (sName==NULL) return getNullName(); const Name* result = NULL; { RBX::mutex::scoped_lock lock(mutex()); const Name& (*thisFunction)(const char* const &) = &RBX::Name::lookup; // required due to overload. checkRbxCaller<kCallCheckCallersCode, callCheckSetApiFlag<kNameApiOffset> >( reinterpret_cast<void*>(thisFunction)); NameMap::iterator iter = map().find(sName); if (iter!=map().end()) result = iter->second; } // Avoid recursively locking mutex(). return result != NULL ? *result : Name::getNullName(); } std::ostream& RBX::operator<<( std::ostream& os, const Name& name ) { return os << name.c_str(); }