X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.h;h=34ccecac75a08dae5d16c74251a4c52f7b74f08e;hb=b4f8c8f5f9ff0f8db6612d7f279976453b18876f;hp=32445951640218166a961063a925742b3c800594;hpb=31f293128177e0f53331ddb3f1f5ea22176bf91c;p=novacoin.git diff --git a/src/util.h b/src/util.h index 3244595..34cceca 100644 --- a/src/util.h +++ b/src/util.h @@ -1,4 +1,5 @@ // 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. #ifndef BITCOIN_UTIL_H @@ -6,7 +7,7 @@ #include "uint256.h" -#ifndef __WXMSW__ +#ifndef WIN32 #include #include #include @@ -64,15 +65,7 @@ typedef unsigned long long uint64; #endif // This is needed because the foreach macro can't get over the comma in pair -#define PAIRTYPE(t1, t2) pair - -// Used to bypass the rule against non-const reference to temporary -// where it makes sense with wrappers such as CFlatData or CTxDB -template -inline T& REF(const T& val) -{ - return (T&)val; -} +#define PAIRTYPE(t1, t2) std::pair // Align by increasing pointer, must have extra space at end of buffer template @@ -88,7 +81,7 @@ T* alignup(T* p) return u.ptr; } -#ifdef __WXMSW__ +#ifdef WIN32 #define MSG_NOSIGNAL 0 #define MSG_DONTWAIT 0 #ifndef UINT64_MAX @@ -104,6 +97,8 @@ T* alignup(T* p) typedef int socklen_t; #else #define WSAGetLastError() errno +#define WSAEINVAL EINVAL +#define WSAEALREADY EALREADY #define WSAEWOULDBLOCK EWOULDBLOCK #define WSAEMSGSIZE EMSGSIZE #define WSAEINTR EINTR @@ -120,7 +115,9 @@ typedef u_int SOCKET; #define Beep(n1,n2) (0) inline void Sleep(int64 n) { - boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n)); + /*Boost has a year 2038 problem— if the request sleep time is past epoch+2^31 seconds the sleep returns instantly. + So we clamp our sleeps here to 10 years and hope that boost is fixed by 2028.*/ + boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n>315576000000LL?315576000000LL:n)); } #endif @@ -128,7 +125,7 @@ inline int myclosesocket(SOCKET& hSocket) { if (hSocket == INVALID_SOCKET) return WSAENOTSOCK; -#ifdef __WXMSW__ +#ifdef WIN32 int ret = closesocket(hSocket); #else int ret = close(hSocket); @@ -137,8 +134,7 @@ inline int myclosesocket(SOCKET& hSocket) return ret; } #define closesocket(s) myclosesocket(s) - -#ifndef GUI +#if !defined(QT_GUI) inline const char* _(const char* psz) { return psz; @@ -153,7 +149,6 @@ inline const char* _(const char* psz) - extern std::map mapArgs; extern std::map > mapMultiArgs; extern bool fDebug; @@ -174,8 +169,8 @@ void RandAddSeed(); void RandAddSeedPerfmon(); int OutputDebugStringF(const char* pszFormat, ...); int my_snprintf(char* buffer, size_t limit, const char* format, ...); -std::string strprintf(const char* format, ...); -bool error(const char* format, ...); +std::string strprintf(const std::string &format, ...); +bool error(const std::string &format, ...); void LogException(std::exception* pex, const char* pszThread); void PrintException(std::exception* pex, const char* pszThread); void PrintExceptionContinue(std::exception* pex, const char* pszThread); @@ -185,6 +180,10 @@ bool ParseMoney(const std::string& str, int64& nRet); bool ParseMoney(const char* pszIn, int64& nRet); std::vector ParseHex(const char* psz); std::vector ParseHex(const std::string& str); +std::vector DecodeBase64(const char* p, bool* pfInvalid = NULL); +std::string DecodeBase64(const std::string& str); +std::string EncodeBase64(const unsigned char* pch, size_t len); +std::string EncodeBase64(const std::string& str); void ParseParameters(int argc, char* argv[]); const char* wxGetTranslation(const char* psz); bool WildcardMatch(const char* psz, const char* mask); @@ -195,7 +194,7 @@ std::string GetConfigFile(); std::string GetPidFile(); void CreatePidFile(std::string pidFile, pid_t pid); void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); -#ifdef __WXMSW__ +#ifdef WIN32 std::string MyGetSpecialFolderPath(int nFolder, bool fCreate); #endif std::string GetDefaultDataDir(); @@ -204,6 +203,7 @@ void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); int64 GetTime(); +void SetMockTime(int64 nMockTimeIn); int64 GetAdjustedTime(); void AddTimeData(unsigned int ip, int64 nTime); std::string FormatFullVersion(); @@ -220,31 +220,17 @@ std::string FormatFullVersion(); -// Wrapper to automatically initialize critical sections +// Wrapper to automatically initialize mutex class CCriticalSection { -#ifdef __WXMSW__ -protected: - CRITICAL_SECTION cs; -public: - explicit CCriticalSection() { InitializeCriticalSection(&cs); } - ~CCriticalSection() { DeleteCriticalSection(&cs); } - void Enter() { EnterCriticalSection(&cs); } - void Leave() { LeaveCriticalSection(&cs); } - bool TryEnter() { return TryEnterCriticalSection(&cs); } -#else protected: boost::interprocess::interprocess_recursive_mutex mutex; public: explicit CCriticalSection() { } ~CCriticalSection() { } - void Enter() { mutex.lock(); } - void Leave() { mutex.unlock(); } - bool TryEnter() { return mutex.try_lock(); } -#endif -public: - const char* pszFile; - int nLine; + void Enter(const char* pszName, const char* pszFile, int nLine); + void Leave(); + bool TryEnter(const char* pszName, const char* pszFile, int nLine); }; // Automatically leave critical section when leaving block, needed for exception safety @@ -252,9 +238,17 @@ class CCriticalBlock { protected: CCriticalSection* pcs; + public: - CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); } - ~CCriticalBlock() { pcs->Leave(); } + CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + { + pcs = &csIn; + pcs->Enter(pszName, pszFile, nLine); + } + ~CCriticalBlock() + { + pcs->Leave(); + } }; // WARNING: This will catch continue and break! @@ -262,27 +256,47 @@ public: // I'd rather be careful than suffer the other more error prone syntax. // The compiler will optimise away all this loop junk. #define CRITICAL_BLOCK(cs) \ - for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \ - for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) + for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \ + for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false) + +#define ENTER_CRITICAL_SECTION(cs) \ + (cs).Enter(#cs, __FILE__, __LINE__) + +#define LEAVE_CRITICAL_SECTION(cs) \ + (cs).Leave() class CTryCriticalBlock { protected: CCriticalSection* pcs; + public: - CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); } - ~CTryCriticalBlock() { if (pcs) pcs->Leave(); } + CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + { + pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); + } + ~CTryCriticalBlock() + { + if (pcs) + { + pcs->Leave(); + } + } bool Entered() { return pcs != NULL; } }; #define TRY_CRITICAL_BLOCK(cs) \ - for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \ - for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0) + for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \ + for (CTryCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()); fcriticalblockonce=false) + +// This is exactly like std::string, but with a custom allocator. +// (secure_allocator<> is defined in serialize.h) +typedef std::basic_string, secure_allocator > SecureString; @@ -388,7 +402,7 @@ inline void PrintHex(const std::vector& vch, const char* pszForma inline int64 GetPerformanceCounter() { int64 nCounter = 0; -#ifdef __WXMSW__ +#ifdef WIN32 QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); #else timeval t; @@ -422,7 +436,7 @@ void skipspaces(T& it) inline bool IsSwitchChar(char c) { -#ifdef __WXMSW__ +#ifdef WIN32 return c == '-' || c == '/'; #else return c == '-'; @@ -443,7 +457,7 @@ inline int64 GetArg(const std::string& strArg, int64 nDefault) return nDefault; } -inline bool GetBoolArg(const std::string& strArg) +inline bool GetBoolArg(const std::string& strArg, bool fDefault=false) { if (mapArgs.count(strArg)) { @@ -451,9 +465,26 @@ inline bool GetBoolArg(const std::string& strArg) return true; return (atoi(mapArgs[strArg]) != 0); } - return false; + return fDefault; } +/** + * Set an argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValue Value (e.g. "1") + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, const std::string& strValue); + +/** + * Set a boolean argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param fValue Value (e.g. false) + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, bool fValue); @@ -465,7 +496,7 @@ inline bool GetBoolArg(const std::string& strArg) inline void heapchk() { -#ifdef __WXMSW__ +#ifdef WIN32 /// for debugging //if (_heapchk() != _HEAPOK) // DebugBreak(); @@ -568,6 +599,51 @@ inline uint160 Hash160(const std::vector& vch) } +// Median filter over a stream of values +// Returns the median of the last N numbers +template class CMedianFilter +{ +private: + std::vector vValues; + std::vector vSorted; + int nSize; +public: + CMedianFilter(int size, T initial_value): + nSize(size) + { + vValues.reserve(size); + vValues.push_back(initial_value); + vSorted = vValues; + } + + void input(T value) + { + if(vValues.size() == nSize) + { + vValues.erase(vValues.begin()); + } + vValues.push_back(value); + + vSorted.resize(vValues.size()); + std::copy(vValues.begin(), vValues.end(), vSorted.begin()); + std::sort(vSorted.begin(), vSorted.end()); + } + + T median() const + { + int size = vSorted.size(); + assert(size>0); + if(size & 1) // Odd number of elements + { + return vSorted[size/2]; + } + else // Even number of elements + { + return (vSorted[size/2-1] + vSorted[size/2]) / 2; + } + } +}; + @@ -579,7 +655,7 @@ inline uint160 Hash160(const std::vector& vch) // Note: It turns out we might have been able to use boost::thread // by using TerminateThread(boost::thread.native_handle(), 0); -#ifdef __WXMSW__ +#ifdef WIN32 typedef HANDLE pthread_t; inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) @@ -621,7 +697,10 @@ inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=fa return (pthread_t)0; } if (!fWantHandle) + { + pthread_detach(hthread); return (pthread_t)-1; + } return hthread; } @@ -646,7 +725,7 @@ inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode) return (pthread_cancel(hthread) == 0); } -inline void ExitThread(unsigned int nExitCode) +inline void ExitThread(size_t nExitCode) { pthread_exit((void*)nExitCode); } @@ -658,10 +737,10 @@ inline void ExitThread(unsigned int nExitCode) inline bool AffinityBugWorkaround(void(*pfn)(void*)) { -#ifdef __WXMSW__ +#ifdef WIN32 // Sometimes after a few hours affinity gets stuck on one processor - DWORD dwProcessAffinityMask = -1; - DWORD dwSystemAffinityMask = -1; + DWORD_PTR dwProcessAffinityMask = -1; + DWORD_PTR dwSystemAffinityMask = -1; GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask); DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask); DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask); @@ -676,4 +755,10 @@ inline bool AffinityBugWorkaround(void(*pfn)(void*)) return false; } +inline uint32_t ByteReverse(uint32_t value) +{ + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return (value<<16) | (value>>16); +} + #endif