mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-08 02:54:56 -06:00
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
This commit is contained in:
parent
30967af389
commit
e3df5fdc3f
3 changed files with 91 additions and 46 deletions
|
|
@ -50,12 +50,13 @@ VectorMap<String, String> 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<String, String> 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<IniInt&>(*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<IniInt64&>(*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<IniDouble&>(*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<IniBool&>(*this));
|
||||
}
|
||||
|
||||
|
||||
Array<IniInfo>& sIniInfo()
|
||||
{
|
||||
static Array<IniInfo> s;
|
||||
|
|
|
|||
|
|
@ -471,6 +471,19 @@ inline bool IsMainThread() { return true; }
|
|||
|
||||
typedef int Atomic;
|
||||
|
||||
template <class U>
|
||||
inline U ReadWithBarrier(const U& b)
|
||||
{
|
||||
/*volatile*/ U tmp = b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class U, class V>
|
||||
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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue