From e3df5fdc3fea22ff36eb05d2681973c715f203c8 Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 24 Jul 2012 07:18:27 +0000 Subject: [PATCH] Core: INI_ system now using double checked locking to avoid mutexes git-svn-id: svn://ultimatepp.org/upp/trunk@5231 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Ini.cpp | 81 +++++++++++++++++++++++++++------------------ uppsrc/Core/Mt.h | 13 ++++++++ uppsrc/Core/Util.h | 43 ++++++++++++++++-------- 3 files changed, 91 insertions(+), 46 deletions(-) diff --git a/uppsrc/Core/Ini.cpp b/uppsrc/Core/Ini.cpp index 61efda82e..7e23c5ca3 100644 --- a/uppsrc/Core/Ini.cpp +++ b/uppsrc/Core/Ini.cpp @@ -50,12 +50,13 @@ VectorMap LoadIniFile(const char *filename) { static StaticMutex sMtx; static char sIniFile[256]; -static int64 s_ini_version = 1; + +int ini_version__ = 1; void ReloadIniFile() { Mutex::Lock __(sMtx); - s_ini_version++; + ini_version__++; } void SetIniFile(const char *name) { @@ -64,28 +65,24 @@ void SetIniFile(const char *name) { ReloadIniFile(); } -static -void sIniSet(int64& version) +void IniSet__(int& version) { - version = s_ini_version; + BarrierWrite(version, ini_version__); } - -static -bool sIniChanged(int64& version) +#ifdef flagSO +bool IniChanged__(int version) { - if(version != s_ini_version) { - version = s_ini_version; - return true; - } - return false; + return version != ReadWithBarrier(ini_version__); } +#endif String GetIniKey(const char *id, const String& def) { Mutex::Lock __(sMtx); static VectorMap key; - static int64 version; - if(sIniChanged(version)) { + static int version; + if(version != ini_version__) { + version = ini_version__; key = LoadIniFile(*sIniFile ? sIniFile : ~ConfigFile("q.ini")); #ifdef PLATFORM_WIN32 if(key.GetCount() == 0) @@ -106,27 +103,36 @@ String GetIniKey(const char *id) return GetIniKey(id, String()); } -IniString::operator String() +String IniString::Load() { String x; { Mutex::Lock __(sMtx); String& s = (*ref_fn)(); - if(sIniChanged(version)) { + if(IniChanged__(version)) { s = TrimBoth(GetIniKey(id)); if(IsNull(s)) s = (*def)(); } x = s; + IniSet__(version); } return x; } +IniString::operator String() +{ + String h = (*ref_fn)(); + if(IniChanged__(version)) + return Load(); + return h; +} + String IniString::operator=(const String& s) { Mutex::Lock __(sMtx); (*ref_fn)() = s; - sIniSet(version); + IniSet__(version); return s; } @@ -167,19 +173,20 @@ int64 ReadIniInt(const char *id) return num; } -IniInt::operator int() { +int IniInt::Load() { Mutex::Lock __(sMtx); - if(sIniChanged(version)) { + if(IniChanged__(version)) { value = (int)ReadIniInt(id); if(IsNull(value)) value = (*def)(); + IniSet__(version); } return value; } int IniInt::operator=(int b) { Mutex::Lock __(sMtx); - sIniSet(version); + IniSet__(version); return value = b; } @@ -188,13 +195,14 @@ String IniInt::ToString() const return AsString((int)const_cast(*this)); } -IniInt64::operator int64() +int64 IniInt64::Load() { Mutex::Lock __(sMtx); - if(sIniChanged(version)) { + if(IniChanged__(version)) { value = ReadIniInt(id); if(IsNull(value)) value = (*def)(); + IniSet__(version); } return value; } @@ -202,7 +210,9 @@ IniInt64::operator int64() int64 IniInt64::operator=(int64 b) { Mutex::Lock __(sMtx); - sIniSet(version); + BarrierWrite(version, -1); + value = b; + IniSet__(version); return value = b; } @@ -211,13 +221,14 @@ String IniInt64::ToString() const return AsString((int64)const_cast(*this)); } -IniDouble::operator double() +double IniDouble::Load() { Mutex::Lock __(sMtx); - if(sIniChanged(version)) { + if(IniChanged__(version)) { value = ScanDouble(TrimBoth(ToLower(GetIniKey(id)))); if(IsNull(value)) value = (*def)(); + IniSet__(version); } return value; } @@ -225,8 +236,10 @@ IniDouble::operator double() double IniDouble::operator=(double b) { Mutex::Lock __(sMtx); - sIniSet(version); - return value = b; + BarrierWrite(version, -1); + value = b; + IniSet__(version); + return b; } String IniDouble::ToString() const @@ -234,22 +247,25 @@ String IniDouble::ToString() const return AsString((double)const_cast(*this)); } -IniBool::operator bool() { +bool IniBool::Load() { Mutex::Lock __(sMtx); - if(sIniChanged(version)) { + if(IniChanged__(version)) { String h = TrimBoth(ToLower(GetIniKey(id))); if(h.GetCount()) value = h == "1" || h == "yes" || h == "true" || h == "y"; else value = (*def)(); + IniSet__(version); } return value; } bool IniBool::operator=(bool b) { Mutex::Lock __(sMtx); - sIniSet(version); - return value = b; + BarrierWrite(version, -1); + value = b; + IniSet__(version); + return b; } String IniBool::ToString() const @@ -257,7 +273,6 @@ String IniBool::ToString() const return AsString((bool)const_cast(*this)); } - Array& sIniInfo() { static Array s; diff --git a/uppsrc/Core/Mt.h b/uppsrc/Core/Mt.h index 6ce2d8284..7ac9ac2dc 100644 --- a/uppsrc/Core/Mt.h +++ b/uppsrc/Core/Mt.h @@ -471,6 +471,19 @@ inline bool IsMainThread() { return true; } typedef int Atomic; +template +inline U ReadWithBarrier(const U& b) +{ + /*volatile*/ U tmp = b; + return tmp; +} + +template +inline void BarrierWrite(U& dest, V data) +{ + dest = data; +} + inline int AtomicRead(const volatile Atomic& t) { return t; } inline void AtomicWrite(volatile Atomic& t, int data) { t = data; } diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index b89f4ce09..74ef85b66 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -29,12 +29,21 @@ void SetIniFile(const char *path = NULL); String GetIniKey(const char *id, const String& def); String GetIniKey(const char *id); +#ifdef flagSO +bool IniChanged__(int version); +#else +extern int ini_version__; +inline bool IniChanged__(int version) { return version != ReadWithBarrier(ini_version__); } +#endif + struct IniString { // "private": const char *id; String (*def)(); String& (*ref_fn)(); - int64 version; + int version; + String Load(); + // "public:" operator String(); String operator=(const String& s); @@ -44,11 +53,13 @@ struct IniString { struct IniInt { // "private": const char *id; - int (*def)(); - int64 version; - int value; + int (*def)(); + int version; + int value; + int Load(); + // "public:" - operator int(); + operator int() { int h = value; if(IniChanged__(version)) return Load(); return h; } int operator=(int b); String ToString() const; }; @@ -56,11 +67,13 @@ struct IniInt { struct IniInt64 { // "private": const char *id; - int64 (*def)(); - int64 version; - int64 value; + int64 (*def)(); + int version; + int64 value; + int64 Load(); + // "public:" - operator int64(); + operator int64() { int64 h = value; if(IniChanged__(version)) return Load(); return h; } int64 operator=(int64 b); String ToString() const; }; @@ -69,10 +82,12 @@ struct IniDouble { // "private": const char *id; double (*def)(); - int64 version; + int version; double value; + double Load(); + // "public:" - operator double(); + operator double() { double h = value; if(IniChanged__(version)) return Load(); return h; } double operator=(double b); String ToString() const; }; @@ -81,10 +96,12 @@ struct IniBool { // "private": const char *id; bool (*def)(); - int64 version; + int version; bool value; + bool Load(); + // "public:" - operator bool(); + operator bool() { bool h = value; if(IniChanged__(version)) return Load(); return h; } bool operator=(bool b); String ToString() const; };