// 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.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UTIL_H
#define BITCOIN_UTIL_H
#include <string>
#include <boost/thread.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
-#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/sync/lock_options.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
-#include "netbase.h"
+#include "netbase.h" // for AddTimeData
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]))
extern bool fDebug;
extern bool fPrintToConsole;
extern bool fPrintToDebugger;
-extern char pszSetDataDir[MAX_PATH];
extern bool fRequestShutdown;
extern bool fShutdown;
extern bool fDaemon;
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<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& 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<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& 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();
typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection;
#ifdef DEBUG_LOCKORDER
-void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs);
+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) {}
+void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
#endif
{
printf("LOCKCONTENTION: %s\n", pszName);
printf("Locker: %s:%d\n", pszFile, nLine);
- }
#endif
lock.lock();
+#ifdef DEBUG_LOCKCONTENTION
+ }
+#endif
}
}
{
if (!lock.owns())
{
- EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
+ EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
lock.try_lock();
if (!lock.owns())
LeaveCritical();
};
typedef CMutexLock<CCriticalSection> CCriticalBlock;
-typedef CMutexLock<CWaitableCriticalSection> 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) \
{ \
LeaveCritical(); \
}
+#ifdef MAC_OSX
+// boost::interprocess::interprocess_semaphore seems to spinlock on OSX; prefer polling instead
+class CSemaphore
+{
+private:
+ CCriticalSection cs;
+ int val;
-// This is exactly like std::string, but with a custom allocator.
-// (secure_allocator<> is defined in serialize.h)
-typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
-
+public:
+ CSemaphore(int init) : val(init) {}
+ void wait() {
+ do {
+ {
+ LOCK(cs);
+ if (val>0) {
+ val--;
+ return;
+ }
+ }
+ Sleep(100);
+ } while(1);
+ }
+ bool try_wait() {
+ LOCK(cs);
+ if (val>0) {
+ val--;
+ return true;
+ }
+ return false;
+ }
+ void post() {
+ LOCK(cs);
+ val++;
+ }
+};
+#else
+typedef boost::interprocess::interprocess_semaphore CSemaphore;
+#endif
inline std::string i64tostr(int64 n)
{
template<typename T>
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<char> 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<unsigned char>& vch, bool fSpaces=false)
private:
std::vector<T> vValues;
std::vector<T> 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);
-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);