X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.cpp;h=85ca02f0aaee74a9d1e1d1b9f74c029a59863538;hb=4664aae3fe2eba4eec84d20f1e7e701ceeeb49bd;hp=61991092895281d34e51c17c91492e05f28c9e3f;hpb=77172463a30a5837a0a53ddfd7fb578343d2a33f;p=novacoin.git diff --git a/src/util.cpp b/src/util.cpp index 6199109..85ca02f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,7 +1,16 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" +#include "strlcpy.h" +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace boost; @@ -338,11 +347,6 @@ string FormatMoney(int64 n, bool fPlus) if (nTrim) str.erase(str.size()-nTrim, nTrim); - // Insert thousands-separators: - size_t point = str.find("."); - for (int i = (str.size()-point)+3; i < str.size(); i += 4) - if (isdigit(str[str.size() - i - 1])) - str.insert(str.size() - i, 1, ','); if (n < 0) str.insert((unsigned int)0, 1, '-'); else if (fPlus && n > 0) @@ -365,8 +369,6 @@ bool ParseMoney(const char* pszIn, int64& nRet) p++; for (; *p; p++) { - if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4])) - continue; if (*p == '.') { p++; @@ -387,7 +389,7 @@ bool ParseMoney(const char* pszIn, int64& nRet) for (; *p; p++) if (!isspace(*p)) return false; - if (strWhole.size() > 14) + if (strWhole.size() > 10) // guard against 63 bit overflow return false; if (nUnits < 0 || nUnits > COIN) return false; @@ -470,6 +472,23 @@ void ParseParameters(int argc, char* argv[]) } } +bool SoftSetArg(const std::string& strArg, const std::string& strValue) +{ + if (mapArgs.count(strArg)) + return false; + mapArgs[strArg] = strValue; + return true; +} + +bool SoftSetArg(const std::string& strArg, bool fValue) +{ + if (fValue) + return SoftSetArg(strArg, std::string("1")); + else + return SoftSetArg(strArg, std::string("0")); +} + + const char* wxGetTranslation(const char* pszEnglish) { @@ -759,8 +778,8 @@ string GetPidFile() void CreatePidFile(string pidFile, pid_t pid) { - FILE* file; - if (file = fopen(pidFile.c_str(), "w")) + FILE* file = fopen(pidFile.c_str(), "w"); + if (file) { fprintf(file, "%d\n", pid); fclose(file); @@ -789,7 +808,9 @@ void ShrinkDebugFile() fseek(file, -sizeof(pch), SEEK_END); int nBytes = fread(pch, 1, sizeof(pch), file); fclose(file); - if (file = fopen(strFile.c_str(), "w")) + + file = fopen(strFile.c_str(), "w"); + if (file) { fwrite(pch, 1, nBytes, file); fclose(file); @@ -895,12 +916,150 @@ string FormatVersion(int nVersion) string FormatFullVersion() { string s = FormatVersion(VERSION) + pszSubVer; - if (VERSION_IS_BETA) - s += _("-beta"); + if (VERSION_IS_BETA) { + s += "-"; + s += _("beta"); + } return s; } +#ifdef DEBUG_LOCKORDER +// +// Early deadlock detection. +// Problem being solved: +// Thread 1 locks A, then B, then C +// Thread 2 locks D, then C, then A +// --> may result in deadlock between the two threads, depending on when they run. +// Solution implemented here: +// Keep track of pairs of locks: (A before B), (A before C), etc. +// Complain if any thread trys to lock in a different order. +// + +struct CLockLocation +{ + CLockLocation(const char* pszName, const char* pszFile, int nLine) + { + mutexName = pszName; + sourceFile = pszFile; + sourceLine = nLine; + } + + std::string ToString() const + { + return mutexName+" "+sourceFile+":"+itostr(sourceLine); + } + +private: + std::string mutexName; + std::string sourceFile; + int sourceLine; +}; + +typedef std::vector< std::pair > LockStack; + +static boost::interprocess::interprocess_mutex dd_mutex; +static std::map, LockStack> lockorders; +static boost::thread_specific_ptr lockstack; + + +static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) +{ + printf("POTENTIAL DEADLOCK DETECTED\n"); + printf("Previous lock order was:\n"); + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) + { + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); + } + printf("Current lock order is:\n"); + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) + { + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); + } +} + +static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) +{ + bool fOrderOK = true; + if (lockstack.get() == NULL) + lockstack.reset(new LockStack); + + if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str()); + dd_mutex.lock(); + + (*lockstack).push_back(std::make_pair(c, locklocation)); + + BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack)) + { + if (i.first == c) break; + + std::pair p1 = std::make_pair(i.first, c); + if (lockorders.count(p1)) + continue; + lockorders[p1] = (*lockstack); + + std::pair p2 = std::make_pair(c, i.first); + if (lockorders.count(p2)) + { + potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); + break; + } + } + dd_mutex.unlock(); +} + +static void pop_lock() +{ + if (fDebug) + { + const CLockLocation& locklocation = (*lockstack).rbegin()->second; + printf("Unlocked: %s\n", locklocation.ToString().c_str()); + } + dd_mutex.lock(); + (*lockstack).pop_back(); + dd_mutex.unlock(); +} + +void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine) +{ + push_lock(this, CLockLocation(pszName, pszFile, nLine)); + mutex.lock(); +} +void CCriticalSection::Leave() +{ + mutex.unlock(); + pop_lock(); +} +bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine) +{ + push_lock(this, CLockLocation(pszName, pszFile, nLine)); + bool result = mutex.try_lock(); + if (!result) pop_lock(); + return result; +} + +#else + +void CCriticalSection::Enter(const char*, const char*, int) +{ + mutex.lock(); +} + +void CCriticalSection::Leave() +{ + mutex.unlock(); +} + +bool CCriticalSection::TryEnter(const char*, const char*, int) +{ + bool result = mutex.try_lock(); + return result; +} +#endif /* DEBUG_LOCKORDER */