X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.h;h=a4424771ced2e46ffc3b983c7c026f32fcf90485;hb=ed6d0b5f852dc5f1c9407abecb5a9c6a7e42b4b2;hp=4fa5a08982b3e624df20d39080b9726887b060f2;hpb=6b8de05d0a6696dff4b7dccec5b74889f3cdc486;p=novacoin.git diff --git a/src/util.h b/src/util.h index 4fa5a08..a442477 100644 --- a/src/util.h +++ b/src/util.h @@ -11,24 +11,35 @@ #include #include #include +#else +typedef int pid_t; /* define for windows compatiblity */ #endif #include #include #include #include +#include +#include #include +#include +#include +#include #include #include #include #include -#include "netbase.h" +#include "netbase.h" // for AddTimeData +#include "ui_interface.h" typedef long long int64; typedef unsigned long long uint64; +static const int64 COIN = 100000000; +static const int64 CENT = 1000000; + #define loop for (;;) #define BEGIN(a) ((char*)&(a)) #define END(a) ((char*)&((&(a))[1])) @@ -93,13 +104,6 @@ inline void Sleep(int64 n) } #endif -#if !defined(QT_GUI) -inline const char* _(const char* psz) -{ - return psz; -} -#endif - @@ -113,7 +117,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; @@ -128,8 +131,15 @@ void RandAddSeed(); void RandAddSeedPerfmon(); int OutputDebugStringF(const char* pszFormat, ...); int my_snprintf(char* buffer, size_t limit, const char* format, ...); -std::string strprintf(const std::string &format, ...); -bool error(const std::string &format, ...); + +/* It is not allowed to use va_start with a pass-by-reference argument. + (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a + macro to keep similar semantics. +*/ +std::string real_strprintf(const std::string &format, int dummy, ...); +#define strprintf(format, ...) real_strprintf(format, 0, __VA_ARGS__) + +bool error(const char *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); @@ -148,16 +158,14 @@ 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); +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); bool ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); -#ifdef WIN32 -std::string MyGetSpecialFolderPath(int nFolder, bool fCreate); -#endif -std::string GetDefaultDataDir(); -std::string GetDataDir(); +bool GetStartOnSystemStartup(); +bool SetStartOnSystemStartup(bool fAutoStart); void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); @@ -178,86 +186,121 @@ void AddTimeData(const CNetAddr& ip, int64 nTime); +/** Wrapped boost mutex: supports recursive locking, but no waiting */ +typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection; -/** Wrapper to automatically initialize mutex. */ -class CCriticalSection -{ -protected: - boost::interprocess::interprocess_recursive_mutex mutex; -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); -}; +/** Wrapped boost mutex: supports waiting but not recursive locking */ +typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection; -/** RAII object that acquires mutex. Needed for exception safety. */ -class CCriticalBlock -{ -protected: - CCriticalSection* pcs; +#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 +{ +private: + boost::interprocess::scoped_lock lock; public: - CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + + void Enter(const char* pszName, const char* pszFile, int nLine) { - pcs = &csIn; - pcs->Enter(pszName, pszFile, 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(); + } } - operator bool() const + void Leave() { - return true; + if (lock.owns()) + { + lock.unlock(); + LeaveCritical(); + } } - ~CCriticalBlock() + bool TryEnter(const char* pszName, const char* pszFile, int nLine) { - pcs->Leave(); + if (!lock.owns()) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); + lock.try_lock(); + if (!lock.owns()) + LeaveCritical(); + } + return lock.owns(); } -}; - -#define CRITICAL_BLOCK(cs) \ - if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__)) - -#define ENTER_CRITICAL_SECTION(cs) \ - (cs).Enter(#cs, __FILE__, __LINE__) -#define LEAVE_CRITICAL_SECTION(cs) \ - (cs).Leave() - -/** RAII object that tries to acquire mutex. Needed for exception safety. */ -class CTryCriticalBlock -{ -protected: - CCriticalSection* pcs; + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock) + { + if (fTry) + TryEnter(pszName, pszFile, nLine); + else + Enter(pszName, pszFile, nLine); + } -public: - CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) + ~CMutexLock() { - pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); + if (lock.owns()) + LeaveCritical(); } - operator bool() const + operator bool() { - return Entered(); + return lock.owns(); } - ~CTryCriticalBlock() + boost::interprocess::scoped_lock &GetLock() { - if (pcs) - { - pcs->Leave(); - } + return lock; } - bool Entered() const { return pcs != NULL; } }; -#define TRY_CRITICAL_BLOCK(cs) \ - if (CTryCriticalBlock criticalblock = CTryCriticalBlock(cs, #cs, __FILE__, __LINE__)) +typedef CMutexLock CCriticalBlock; +typedef CMutexLock CWaitableCriticalBlock; +typedef boost::interprocess::interprocess_condition CConditionVariable; +/** Wait for a given condition inside a WAITABLE_CRITICAL_BLOCK */ +#define WAIT(name,condition) \ + do { while(!(condition)) { (name).wait(waitablecriticalblock.GetLock()); } } while(0) +/** Notify waiting threads that a condition may hold now */ +#define NOTIFY(name) \ + do { (name).notify_one(); } while(0) +#define NOTIFY_ALL(name) \ + do { (name).notify_all(); } while(0) +#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 WAITABLE_LOCK(cs) CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__) + +#define ENTER_CRITICAL_SECTION(cs) \ + { \ + EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ + (cs).lock(); \ + } + +#define LEAVE_CRITICAL_SECTION(cs) \ + { \ + (cs).unlock(); \ + LeaveCritical(); \ + } // This is exactly like std::string, but with a custom allocator. @@ -666,26 +709,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);