X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.h;h=5f46849f66ac3405c05b496a9ac2d1936d933723;hb=3176e0f244d929669aa3e1d81e0787d82d9150d3;hp=e4cf83f4337c57204c1c0e995e12a520fcf4eb4c;hpb=5d7cebdadc991a23195a3519c1e9c038cb4f2290;p=novacoin.git diff --git a/src/util.h b/src/util.h index e4cf83f..5f46849 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])) @@ -39,6 +48,11 @@ typedef unsigned long long uint64; #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) #define printf OutputDebugStringF +#define UVOIDBEGIN(a) ((void*)&(a)) +#define CVOIDBEGIN(a) ((const void*)&(a)) +#define UINTBEGIN(a) ((uint32_t*)&(a)) +#define CUINTBEGIN(a) ((const uint32_t*)&(a)) + #ifdef snprintf #undef snprintf #endif @@ -95,8 +109,14 @@ inline void Sleep(int64 n) } #endif - - +#ifndef THROW_WITH_STACKTRACE +#define THROW_WITH_STACKTRACE(exception) \ +{ \ + LogStackTrace(); \ + throw (exception); \ +} +void LogStackTrace(); +#endif @@ -108,7 +128,6 @@ 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; @@ -150,19 +169,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(); @@ -180,85 +198,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() { - pcs = &csIn; - pcs->Enter(pszName, pszFile, nLine); + if (lock.owns()) + { + lock.unlock(); + LeaveCritical(); + } } - operator bool() const + bool TryEnter(const char* pszName, const char* pszFile, int nLine) { - return true; + if (!lock.owns()) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); + lock.try_lock(); + if (!lock.owns()) + LeaveCritical(); + } + return lock.owns(); } - ~CCriticalBlock() + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock) { - pcs->Leave(); + if (fTry) + TryEnter(pszName, pszFile, nLine); + else + Enter(pszName, pszFile, nLine); + } + + ~CMutexLock() + { + if (lock.owns()) + LeaveCritical(); + } + + operator bool() + { + 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) { @@ -311,15 +395,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) @@ -366,6 +455,12 @@ inline std::string DateTimeStrFormat(const char* pszFormat, int64 nTime) return pszTime; } +static const std::string strTimestampFormat = "%Y-%m-%d %H:%M:%S UTC"; +inline std::string DateTimeStrFormat(int64 nTime) +{ + return DateTimeStrFormat(strTimestampFormat.c_str(), nTime); +} + template void skipspaces(T& it) { @@ -524,9 +619,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); @@ -584,9 +679,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 = @@ -600,12 +695,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; } @@ -658,26 +753,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);