X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.h;h=dc40af5e02e52860946b70d1078946028633efaf;hb=0561bbd1c69263dceb24ffacf850788e6e961a13;hp=0b73549dc7ccdfd3e4c2a7653356792219d12b47;hpb=6cb6d623479c5dd42d91de7a4d391078d0800e54;p=novacoin.git diff --git a/src/util.h b/src/util.h index 0b73549..dc40af5 100644 --- a/src/util.h +++ b/src/util.h @@ -1,7 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers +// Copyright (c) 2012 The PPCoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_UTIL_H #define BITCOIN_UTIL_H @@ -19,18 +20,26 @@ typedef int pid_t; /* define for windows compatiblity */ #include #include +#include +#include #include +#include +#include +#include #include #include #include #include -#include "netbase.h" +#include "netbase.h" // for AddTimeData typedef long long int64; typedef unsigned long long uint64; +static const int64 COIN = 1000000; +static const int64 CENT = 10000; + #define loop for (;;) #define BEGIN(a) ((char*)&(a)) #define END(a) ((char*)&((&(a))[1])) @@ -95,11 +104,13 @@ inline void Sleep(int64 n) } #endif -#if !defined(QT_GUI) -inline const char* _(const char* psz) -{ - return psz; +#ifndef THROW_WITH_STACKTRACE +#define THROW_WITH_STACKTRACE(exception) \ +{ \ + LogStackTrace(); \ + throw (exception); \ } +void LogStackTrace(); #endif @@ -107,15 +118,11 @@ inline const char* _(const char* psz) - - - extern std::map mapArgs; extern std::map > mapMultiArgs; extern bool fDebug; extern bool fPrintToConsole; extern bool fPrintToDebugger; -extern char pszSetDataDir[MAX_PATH]; extern bool fRequestShutdown; extern bool fShutdown; extern bool fDaemon; @@ -157,19 +164,18 @@ void ParseParameters(int argc, const char*const argv[]); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); int GetFilesize(FILE* file); -void GetDataDir(char* pszDirRet); -std::string GetConfigFile(); -std::string GetPidFile(); -void CreatePidFile(std::string pidFile, pid_t pid); -bool ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); -#ifdef WIN32 -std::string MyGetSpecialFolderPath(int nFolder, bool fCreate); -#endif -std::string GetDefaultDataDir(); -std::string GetDataDir(); +boost::filesystem::path GetDefaultDataDir(); +const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +boost::filesystem::path GetConfigFile(); +boost::filesystem::path GetPidFile(); +void CreatePidFile(const boost::filesystem::path &path, pid_t pid); +void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); +bool GetStartOnSystemStartup(); +bool SetStartOnSystemStartup(bool fAutoStart); void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); +uint256 GetRandHash(); int64 GetTime(); void SetMockTime(int64 nMockTimeIn); int64 GetAdjustedTime(); @@ -187,85 +193,151 @@ void AddTimeData(const CNetAddr& ip, int64 nTime); +/** Wrapped boost mutex: supports recursive locking, but no waiting */ +typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection; + +/** Wrapped boost mutex: supports waiting but not recursive locking */ +typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection; -/** Wrapper to automatically initialize mutex. */ -class CCriticalSection +#ifdef DEBUG_LOCKORDER +void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); +void LeaveCritical(); +#else +void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} +void static inline LeaveCritical() {} +#endif + +/** Wrapper around boost::interprocess::scoped_lock */ +template +class CMutexLock { -protected: - boost::interprocess::interprocess_recursive_mutex mutex; +private: + boost::interprocess::scoped_lock lock; public: - explicit CCriticalSection() { } - ~CCriticalSection() { } - void Enter(const char* pszName, const char* pszFile, int nLine); - void Leave(); - bool TryEnter(const char* pszName, const char* pszFile, int nLine); -}; -/** RAII object that acquires mutex. Needed for exception safety. */ -class CCriticalBlock -{ -protected: - CCriticalSection* pcs; + void Enter(const char* pszName, const char* pszFile, int nLine) + { + if (!lock.owns()) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); +#ifdef DEBUG_LOCKCONTENTION + if (!lock.try_lock()) + { + printf("LOCKCONTENTION: %s\n", pszName); + printf("Locker: %s:%d\n", pszFile, nLine); +#endif + lock.lock(); +#ifdef DEBUG_LOCKCONTENTION + } +#endif + } + } -public: - CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + void Leave() + { + if (lock.owns()) + { + lock.unlock(); + LeaveCritical(); + } + } + + bool TryEnter(const char* pszName, const char* pszFile, int nLine) + { + if (!lock.owns()) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); + lock.try_lock(); + if (!lock.owns()) + LeaveCritical(); + } + return lock.owns(); + } + + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock) { - pcs = &csIn; - pcs->Enter(pszName, pszFile, nLine); + if (fTry) + TryEnter(pszName, pszFile, nLine); + else + Enter(pszName, pszFile, nLine); } - operator bool() const + ~CMutexLock() { - return true; + if (lock.owns()) + LeaveCritical(); } - ~CCriticalBlock() + operator bool() { - pcs->Leave(); + return lock.owns(); + } + + boost::interprocess::scoped_lock &GetLock() + { + return lock; } }; -#define CRITICAL_BLOCK(cs) \ - if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__)) +typedef CMutexLock CCriticalBlock; + +#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) +#define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__) +#define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) #define ENTER_CRITICAL_SECTION(cs) \ - (cs).Enter(#cs, __FILE__, __LINE__) + { \ + EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ + (cs).lock(); \ + } #define LEAVE_CRITICAL_SECTION(cs) \ - (cs).Leave() + { \ + (cs).unlock(); \ + LeaveCritical(); \ + } -/** RAII object that tries to acquire mutex. Needed for exception safety. */ -class CTryCriticalBlock +#ifdef MAC_OSX +// boost::interprocess::interprocess_semaphore seems to spinlock on OSX; prefer polling instead +class CSemaphore { -protected: - CCriticalSection* pcs; +private: + CCriticalSection cs; + int val; public: - CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) - { - pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); + CSemaphore(int init) : val(init) {} + + void wait() { + do { + { + LOCK(cs); + if (val>0) { + val--; + return; + } + } + Sleep(100); + } while(1); } - operator bool() const - { - return Entered(); + bool try_wait() { + LOCK(cs); + if (val>0) { + val--; + return true; + } + return false; } - ~CTryCriticalBlock() - { - if (pcs) - { - pcs->Leave(); - } + void post() { + LOCK(cs); + val++; } - bool Entered() const { return pcs != NULL; } }; - -#define TRY_CRITICAL_BLOCK(cs) \ - if (CTryCriticalBlock criticalblock = CTryCriticalBlock(cs, #cs, __FILE__, __LINE__)) - - - +#else +typedef boost::interprocess::interprocess_semaphore CSemaphore; +#endif inline std::string i64tostr(int64 n) { @@ -318,15 +390,20 @@ inline int64 abs64(int64 n) template std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) { - if (itbegin == itend) - return ""; - const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; - const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); - std::string str; - str.reserve((pend-pbegin) * (fSpaces ? 3 : 2)); - for (const unsigned char* p = pbegin; p != pend; p++) - str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p); - return str; + std::vector rv; + static char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(fSpaces && it != itbegin) + rv.push_back(' '); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + } + + return std::string(rv.begin(), rv.end()); } inline std::string HexStr(const std::vector& vch, bool fSpaces=false) @@ -531,9 +608,9 @@ template class CMedianFilter private: std::vector vValues; std::vector vSorted; - int nSize; + unsigned int nSize; public: - CMedianFilter(int size, T initial_value): + CMedianFilter(unsigned int size, T initial_value): nSize(size) { vValues.reserve(size); @@ -591,9 +668,9 @@ public: // Note: It turns out we might have been able to use boost::thread // by using TerminateThread(boost::thread.native_handle(), 0); #ifdef WIN32 -typedef HANDLE pthread_t; +typedef HANDLE bitcoin_pthread_t; -inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) +inline bitcoin_pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) { DWORD nUnused = 0; HANDLE hthread = @@ -607,12 +684,12 @@ inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=fa if (hthread == NULL) { printf("Error: CreateThread() returned %d\n", GetLastError()); - return (pthread_t)0; + return (bitcoin_pthread_t)0; } if (!fWantHandle) { CloseHandle(hthread); - return (pthread_t)-1; + return (bitcoin_pthread_t)-1; } return hthread; } @@ -665,26 +742,6 @@ inline void ExitThread(size_t nExitCode) -inline bool AffinityBugWorkaround(void(*pfn)(void*)) -{ -#ifdef WIN32 - // Sometimes after a few hours affinity gets stuck on one processor - DWORD_PTR dwProcessAffinityMask = -1; - DWORD_PTR dwSystemAffinityMask = -1; - GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask); - DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask); - DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask); - if (dwPrev2 != dwProcessAffinityMask) - { - printf("AffinityBugWorkaround() : SetThreadAffinityMask=%d, ProcessAffinityMask=%d, restarting thread\n", dwPrev2, dwProcessAffinityMask); - if (!CreateThread(pfn, NULL)) - printf("Error: CreateThread() failed\n"); - return true; - } -#endif - return false; -} - inline uint32_t ByteReverse(uint32_t value) { value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);