Projects : bitcoin : bitcoin_dumpblock_no_losers
| 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
| 2 | // Copyright (c) 2009-2012 The Bitcoin developers |
| 3 | // Distributed under the MIT/X11 software license, see the accompanying |
| 4 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. |
| 5 | #ifndef BITCOIN_UTIL_H |
| 6 | #define BITCOIN_UTIL_H |
| 7 | |
| 8 | #include "uint256.h" |
| 9 | |
| 10 | #include <stdint.h> |
| 11 | #include <sys/types.h> |
| 12 | #include <sys/time.h> |
| 13 | #include <sys/resource.h> |
| 14 | #include <map> |
| 15 | #include <vector> |
| 16 | #include <string> |
| 17 | |
| 18 | #include <boost/thread.hpp> |
| 19 | #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> |
| 20 | #include <boost/date_time/gregorian/gregorian_types.hpp> |
| 21 | #include <boost/date_time/posix_time/posix_time_types.hpp> |
| 22 | |
| 23 | #include <openssl/sha.h> |
| 24 | #include <openssl/ripemd.h> |
| 25 | |
| 26 | |
| 27 | typedef long long int64; |
| 28 | typedef unsigned long long uint64; |
| 29 | |
| 30 | #define __forceinline inline |
| 31 | |
| 32 | #define loop for (;;) |
| 33 | #define BEGIN(a) ((char*)&(a)) |
| 34 | #define END(a) ((char*)&((&(a))[1])) |
| 35 | #define UBEGIN(a) ((unsigned char*)&(a)) |
| 36 | #define UEND(a) ((unsigned char*)&((&(a))[1])) |
| 37 | #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) |
| 38 | #define printf OutputDebugStringF |
| 39 | |
| 40 | #ifdef snprintf |
| 41 | #undef snprintf |
| 42 | #endif |
| 43 | #define snprintf my_snprintf |
| 44 | |
| 45 | #ifndef PRI64d |
| 46 | #define PRI64d "lld" |
| 47 | #define PRI64u "llu" |
| 48 | #define PRI64x "llx" |
| 49 | #endif |
| 50 | |
| 51 | // This is needed because the foreach macro can't get over the comma in pair<t1, t2> |
| 52 | #define PAIRTYPE(t1, t2) std::pair<t1, t2> |
| 53 | |
| 54 | // Align by increasing pointer, must have extra space at end of buffer |
| 55 | template <size_t nBytes, typename T> |
| 56 | T* alignup(T* p) |
| 57 | { |
| 58 | union |
| 59 | { |
| 60 | T* ptr; |
| 61 | size_t n; |
| 62 | } u; |
| 63 | u.ptr = p; |
| 64 | u.n = (u.n + (nBytes-1)) & ~(nBytes-1); |
| 65 | return u.ptr; |
| 66 | } |
| 67 | |
| 68 | #define WSAGetLastError() errno |
| 69 | #define WSAEINVAL EINVAL |
| 70 | #define WSAEALREADY EALREADY |
| 71 | #define WSAEWOULDBLOCK EWOULDBLOCK |
| 72 | #define WSAEMSGSIZE EMSGSIZE |
| 73 | #define WSAEINTR EINTR |
| 74 | #define WSAEINPROGRESS EINPROGRESS |
| 75 | #define WSAEADDRINUSE EADDRINUSE |
| 76 | #define WSAENOTSOCK EBADF |
| 77 | #define INVALID_SOCKET (SOCKET)(~0) |
| 78 | #define SOCKET_ERROR -1 |
| 79 | typedef u_int SOCKET; |
| 80 | #define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) |
| 81 | #define strlwr(psz) to_lower(psz) |
| 82 | #define _strlwr(psz) to_lower(psz) |
| 83 | #define MAX_PATH 1024 |
| 84 | #define Beep(n1,n2) (0) |
| 85 | inline void Sleep(int64 n) |
| 86 | { |
| 87 | /*Boost has a year 2038 problem- if the request sleep time is past epoch+2^31 seconds the sleep returns instantly. |
| 88 | So we clamp our sleeps here to 10 years and hope that boost is fixed by 2028.*/ |
| 89 | boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n>315576000000LL?315576000000LL:n)); |
| 90 | } |
| 91 | |
| 92 | |
| 93 | inline int myclosesocket(SOCKET& hSocket) |
| 94 | { |
| 95 | if (hSocket == INVALID_SOCKET) |
| 96 | return WSAENOTSOCK; |
| 97 | int ret = close(hSocket); |
| 98 | hSocket = INVALID_SOCKET; |
| 99 | return ret; |
| 100 | } |
| 101 | #define closesocket(s) myclosesocket(s) |
| 102 | inline const char* _(const char* psz) |
| 103 | { |
| 104 | return psz; |
| 105 | } |
| 106 | |
| 107 | |
| 108 | extern std::map<std::string, std::string> mapArgs; |
| 109 | extern std::map<std::string, std::vector<std::string> > mapMultiArgs; |
| 110 | extern bool fDebug; |
| 111 | extern bool fPrintToConsole; |
| 112 | extern bool fPrintToDebugger; |
| 113 | extern bool fCanEat; |
| 114 | extern bool fVerifyAll; |
| 115 | extern char pszSetDataDir[MAX_PATH]; |
| 116 | extern bool fRequestShutdown; |
| 117 | extern bool fShutdown; |
| 118 | extern bool fDaemon; |
| 119 | extern bool fServer; |
| 120 | extern bool fCommandLine; |
| 121 | extern std::string strMiscWarning; |
| 122 | extern bool fNoListen; |
| 123 | extern bool fLogTimestamps; |
| 124 | extern std::string CLIENT_NAME; |
| 125 | extern bool fLowS; |
| 126 | extern bool fHighS; |
| 127 | |
| 128 | void RandAddSeed(); |
| 129 | void RandAddSeedPerfmon(); |
| 130 | int OutputDebugStringF(const char* pszFormat, ...); |
| 131 | int my_snprintf(char* buffer, size_t limit, const char* format, ...); |
| 132 | std::string strprintf(const std::string &format, ...); |
| 133 | bool error(const std::string &format, ...); |
| 134 | void LogException(std::exception* pex, const char* pszThread); |
| 135 | void PrintException(std::exception* pex, const char* pszThread); |
| 136 | void PrintExceptionContinue(std::exception* pex, const char* pszThread); |
| 137 | void ParseString(const std::string& str, char c, std::vector<std::string>& v); |
| 138 | std::string FormatMoney(int64 n, bool fPlus=false); |
| 139 | bool ParseMoney(const std::string& str, int64& nRet); |
| 140 | bool ParseMoney(const char* pszIn, int64& nRet); |
| 141 | std::vector<unsigned char> ParseHex(const char* psz); |
| 142 | std::vector<unsigned char> ParseHex(const std::string& str); |
| 143 | std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL); |
| 144 | std::string DecodeBase64(const std::string& str); |
| 145 | std::string EncodeBase64(const unsigned char* pch, size_t len); |
| 146 | std::string EncodeBase64(const std::string& str); |
| 147 | void ParseParameters(int argc, char* argv[]); |
| 148 | const char* wxGetTranslation(const char* psz); |
| 149 | bool WildcardMatch(const char* psz, const char* mask); |
| 150 | bool WildcardMatch(const std::string& str, const std::string& mask); |
| 151 | int GetFilesize(FILE* file); |
| 152 | void GetDataDir(char* pszDirRet); |
| 153 | std::string GetConfigFile(); |
| 154 | std::string GetPidFile(); |
| 155 | void CreatePidFile(std::string pidFile, pid_t pid); |
| 156 | void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); |
| 157 | std::string GetDefaultDataDir(); |
| 158 | std::string GetDataDir(); |
| 159 | void ShrinkDebugFile(); |
| 160 | int GetRandInt(int nMax); |
| 161 | uint64 GetRand(uint64 nMax); |
| 162 | int64 GetTime(); |
| 163 | void SetMockTime(int64 nMockTimeIn); |
| 164 | int64 GetAdjustedTime(); |
| 165 | void AddTimeData(unsigned int ip, int64 nTime); |
| 166 | std::string FormatFullVersion(); |
| 167 | std::string FormatSubVersion(const std::string& name, int nClientVersion); |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | |
| 177 | |
| 178 | |
| 179 | |
| 180 | |
| 181 | // Wrapper to automatically initialize mutex |
| 182 | class CCriticalSection |
| 183 | { |
| 184 | protected: |
| 185 | boost::interprocess::interprocess_recursive_mutex mutex; |
| 186 | public: |
| 187 | explicit CCriticalSection() { } |
| 188 | ~CCriticalSection() { } |
| 189 | void Enter(const char* pszName, const char* pszFile, int nLine); |
| 190 | void Leave(); |
| 191 | bool TryEnter(const char* pszName, const char* pszFile, int nLine); |
| 192 | }; |
| 193 | |
| 194 | // Automatically leave critical section when leaving block, needed for exception safety |
| 195 | class CCriticalBlock |
| 196 | { |
| 197 | protected: |
| 198 | CCriticalSection* pcs; |
| 199 | |
| 200 | public: |
| 201 | CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) |
| 202 | { |
| 203 | pcs = &csIn; |
| 204 | pcs->Enter(pszName, pszFile, nLine); |
| 205 | } |
| 206 | |
| 207 | operator bool() const |
| 208 | { |
| 209 | return true; |
| 210 | } |
| 211 | |
| 212 | ~CCriticalBlock() |
| 213 | { |
| 214 | pcs->Leave(); |
| 215 | } |
| 216 | }; |
| 217 | |
| 218 | #define CRITICAL_BLOCK(cs) \ |
| 219 | if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__)) |
| 220 | |
| 221 | #define ENTER_CRITICAL_SECTION(cs) \ |
| 222 | (cs).Enter(#cs, __FILE__, __LINE__) |
| 223 | |
| 224 | #define LEAVE_CRITICAL_SECTION(cs) \ |
| 225 | (cs).Leave() |
| 226 | |
| 227 | class CTryCriticalBlock |
| 228 | { |
| 229 | protected: |
| 230 | CCriticalSection* pcs; |
| 231 | |
| 232 | public: |
| 233 | CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) |
| 234 | { |
| 235 | pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); |
| 236 | } |
| 237 | |
| 238 | operator bool() const |
| 239 | { |
| 240 | return Entered(); |
| 241 | } |
| 242 | |
| 243 | ~CTryCriticalBlock() |
| 244 | { |
| 245 | if (pcs) |
| 246 | { |
| 247 | pcs->Leave(); |
| 248 | } |
| 249 | } |
| 250 | bool Entered() const { return pcs != NULL; } |
| 251 | }; |
| 252 | |
| 253 | #define TRY_CRITICAL_BLOCK(cs) \ |
| 254 | if (CTryCriticalBlock criticalblock = CTryCriticalBlock(cs, #cs, __FILE__, __LINE__)) |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | |
| 261 | // This is exactly like std::string, but with a custom allocator. |
| 262 | // (secure_allocator<> is defined in serialize.h) |
| 263 | typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString; |
| 264 | |
| 265 | // This is exactly like std::string, but with a custom allocator. |
| 266 | // (secure_allocator<> is defined in serialize.h) |
| 267 | typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString; |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | |
| 273 | inline std::string i64tostr(int64 n) |
| 274 | { |
| 275 | return strprintf("%"PRI64d, n); |
| 276 | } |
| 277 | |
| 278 | inline std::string itostr(int n) |
| 279 | { |
| 280 | return strprintf("%d", n); |
| 281 | } |
| 282 | |
| 283 | inline int64 atoi64(const char* psz) |
| 284 | { |
| 285 | return strtoll(psz, NULL, 10); |
| 286 | } |
| 287 | |
| 288 | inline int64 atoi64(const std::string& str) |
| 289 | { |
| 290 | return strtoll(str.c_str(), NULL, 10); |
| 291 | } |
| 292 | |
| 293 | inline int atoi(const std::string& str) |
| 294 | { |
| 295 | return atoi(str.c_str()); |
| 296 | } |
| 297 | |
| 298 | inline int roundint(double d) |
| 299 | { |
| 300 | return (int)(d > 0 ? d + 0.5 : d - 0.5); |
| 301 | } |
| 302 | |
| 303 | inline int64 roundint64(double d) |
| 304 | { |
| 305 | return (int64)(d > 0 ? d + 0.5 : d - 0.5); |
| 306 | } |
| 307 | |
| 308 | inline int64 abs64(int64 n) |
| 309 | { |
| 310 | return (n >= 0 ? n : -n); |
| 311 | } |
| 312 | |
| 313 | template<typename T> |
| 314 | std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) |
| 315 | { |
| 316 | if (itbegin == itend) |
| 317 | return ""; |
| 318 | const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; |
| 319 | const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); |
| 320 | std::string str; |
| 321 | str.reserve((pend-pbegin) * (fSpaces ? 3 : 2)); |
| 322 | for (const unsigned char* p = pbegin; p != pend; p++) |
| 323 | str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p); |
| 324 | return str; |
| 325 | } |
| 326 | |
| 327 | inline std::string HexStr(const std::vector<unsigned char>& vch, bool fSpaces=false) |
| 328 | { |
| 329 | return HexStr(vch.begin(), vch.end(), fSpaces); |
| 330 | } |
| 331 | |
| 332 | template<typename T> |
| 333 | std::string HexNumStr(const T itbegin, const T itend, bool f0x=true) |
| 334 | { |
| 335 | if (itbegin == itend) |
| 336 | return ""; |
| 337 | const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; |
| 338 | const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); |
| 339 | std::string str = (f0x ? "0x" : ""); |
| 340 | str.reserve(str.size() + (pend-pbegin) * 2); |
| 341 | for (const unsigned char* p = pend-1; p >= pbegin; p--) |
| 342 | str += strprintf("%02x", *p); |
| 343 | return str; |
| 344 | } |
| 345 | |
| 346 | inline std::string HexNumStr(const std::vector<unsigned char>& vch, bool f0x=true) |
| 347 | { |
| 348 | return HexNumStr(vch.begin(), vch.end(), f0x); |
| 349 | } |
| 350 | |
| 351 | template<typename T> |
| 352 | void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true) |
| 353 | { |
| 354 | printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str()); |
| 355 | } |
| 356 | |
| 357 | inline void PrintHex(const std::vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true) |
| 358 | { |
| 359 | printf(pszFormat, HexStr(vch, fSpaces).c_str()); |
| 360 | } |
| 361 | |
| 362 | inline int64 GetPerformanceCounter() |
| 363 | { |
| 364 | int64 nCounter = 0; |
| 365 | timeval t; |
| 366 | gettimeofday(&t, NULL); |
| 367 | nCounter = t.tv_sec * 1000000 + t.tv_usec; |
| 368 | return nCounter; |
| 369 | } |
| 370 | |
| 371 | inline int64 GetTimeMillis() |
| 372 | { |
| 373 | return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) - |
| 374 | boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds(); |
| 375 | } |
| 376 | |
| 377 | inline std::string DateTimeStrFormat(const char* pszFormat, int64 nTime) |
| 378 | { |
| 379 | time_t n = nTime; |
| 380 | struct tm* ptmTime = gmtime(&n); |
| 381 | char pszTime[200]; |
| 382 | strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime); |
| 383 | return pszTime; |
| 384 | } |
| 385 | |
| 386 | template<typename T> |
| 387 | void skipspaces(T& it) |
| 388 | { |
| 389 | while (isspace(*it)) |
| 390 | ++it; |
| 391 | } |
| 392 | |
| 393 | inline bool IsSwitchChar(char c) |
| 394 | { |
| 395 | return c == '-'; |
| 396 | } |
| 397 | |
| 398 | inline std::string GetArg(const std::string& strArg, const std::string& strDefault) |
| 399 | { |
| 400 | if (mapArgs.count(strArg)) |
| 401 | return mapArgs[strArg]; |
| 402 | return strDefault; |
| 403 | } |
| 404 | |
| 405 | inline int64 GetArg(const std::string& strArg, int64 nDefault) |
| 406 | { |
| 407 | if (mapArgs.count(strArg)) |
| 408 | return atoi64(mapArgs[strArg]); |
| 409 | return nDefault; |
| 410 | } |
| 411 | |
| 412 | inline bool GetBoolArg(const std::string& strArg, bool fDefault=false) |
| 413 | { |
| 414 | if (mapArgs.count(strArg)) |
| 415 | { |
| 416 | if (mapArgs[strArg].empty()) |
| 417 | return true; |
| 418 | return (atoi(mapArgs[strArg]) != 0); |
| 419 | } |
| 420 | return fDefault; |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * Set an argument if it doesn't already have a value |
| 425 | * |
| 426 | * @param strArg Argument to set (e.g. "-foo") |
| 427 | * @param strValue Value (e.g. "1") |
| 428 | * @return true if argument gets set, false if it already had a value |
| 429 | */ |
| 430 | bool SoftSetArg(const std::string& strArg, const std::string& strValue); |
| 431 | |
| 432 | /** |
| 433 | * Set a boolean argument if it doesn't already have a value |
| 434 | * |
| 435 | * @param strArg Argument to set (e.g. "-foo") |
| 436 | * @param fValue Value (e.g. false) |
| 437 | * @return true if argument gets set, false if it already had a value |
| 438 | */ |
| 439 | bool SoftSetArg(const std::string& strArg, bool fValue); |
| 440 | |
| 441 | |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 | |
| 447 | |
| 448 | |
| 449 | inline void heapchk() |
| 450 | { |
| 451 | } |
| 452 | |
| 453 | // Randomize the stack to help protect against buffer overrun exploits |
| 454 | #define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \ |
| 455 | { \ |
| 456 | static char nLoops; \ |
| 457 | if (nLoops <= 0) \ |
| 458 | nLoops = GetRand(20) + 1; \ |
| 459 | if (nLoops-- > 1) \ |
| 460 | { \ |
| 461 | ThreadFn; \ |
| 462 | return; \ |
| 463 | } \ |
| 464 | } |
| 465 | |
| 466 | #define CATCH_PRINT_EXCEPTION(pszFn) \ |
| 467 | catch (std::exception& e) { \ |
| 468 | PrintException(&e, (pszFn)); \ |
| 469 | } catch (...) { \ |
| 470 | PrintException(NULL, (pszFn)); \ |
| 471 | } |
| 472 | |
| 473 | |
| 474 | |
| 475 | |
| 476 | |
| 477 | |
| 478 | |
| 479 | |
| 480 | |
| 481 | |
| 482 | template<typename T1> |
| 483 | inline uint256 Hash(const T1 pbegin, const T1 pend) |
| 484 | { |
| 485 | static unsigned char pblank[1]; |
| 486 | uint256 hash1; |
| 487 | SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); |
| 488 | uint256 hash2; |
| 489 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); |
| 490 | return hash2; |
| 491 | } |
| 492 | |
| 493 | template<typename T1, typename T2> |
| 494 | inline uint256 Hash(const T1 p1begin, const T1 p1end, |
| 495 | const T2 p2begin, const T2 p2end) |
| 496 | { |
| 497 | static unsigned char pblank[1]; |
| 498 | uint256 hash1; |
| 499 | SHA256_CTX ctx; |
| 500 | SHA256_Init(&ctx); |
| 501 | SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); |
| 502 | SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); |
| 503 | SHA256_Final((unsigned char*)&hash1, &ctx); |
| 504 | uint256 hash2; |
| 505 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); |
| 506 | return hash2; |
| 507 | } |
| 508 | |
| 509 | template<typename T1, typename T2, typename T3> |
| 510 | inline uint256 Hash(const T1 p1begin, const T1 p1end, |
| 511 | const T2 p2begin, const T2 p2end, |
| 512 | const T3 p3begin, const T3 p3end) |
| 513 | { |
| 514 | static unsigned char pblank[1]; |
| 515 | uint256 hash1; |
| 516 | SHA256_CTX ctx; |
| 517 | SHA256_Init(&ctx); |
| 518 | SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); |
| 519 | SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); |
| 520 | SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0])); |
| 521 | SHA256_Final((unsigned char*)&hash1, &ctx); |
| 522 | uint256 hash2; |
| 523 | SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); |
| 524 | return hash2; |
| 525 | } |
| 526 | |
| 527 | template<typename T> |
| 528 | uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=VERSION) |
| 529 | { |
| 530 | // Most of the time is spent allocating and deallocating CDataStream's |
| 531 | // buffer. If this ever needs to be optimized further, make a CStaticStream |
| 532 | // class with its buffer on the stack. |
| 533 | CDataStream ss(nType, nVersion); |
| 534 | ss.reserve(10000); |
| 535 | ss << obj; |
| 536 | return Hash(ss.begin(), ss.end()); |
| 537 | } |
| 538 | |
| 539 | inline uint160 Hash160(const std::vector<unsigned char>& vch) |
| 540 | { |
| 541 | uint256 hash1; |
| 542 | SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); |
| 543 | uint160 hash2; |
| 544 | RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); |
| 545 | return hash2; |
| 546 | } |
| 547 | |
| 548 | |
| 549 | // Median filter over a stream of values |
| 550 | // Returns the median of the last N numbers |
| 551 | template <typename T> class CMedianFilter |
| 552 | { |
| 553 | private: |
| 554 | std::vector<T> vValues; |
| 555 | std::vector<T> vSorted; |
| 556 | int nSize; |
| 557 | public: |
| 558 | CMedianFilter(int size, T initial_value): |
| 559 | nSize(size) |
| 560 | { |
| 561 | vValues.reserve(size); |
| 562 | vValues.push_back(initial_value); |
| 563 | vSorted = vValues; |
| 564 | } |
| 565 | |
| 566 | void input(T value) |
| 567 | { |
| 568 | if(vValues.size() == nSize) |
| 569 | { |
| 570 | vValues.erase(vValues.begin()); |
| 571 | } |
| 572 | vValues.push_back(value); |
| 573 | |
| 574 | vSorted.resize(vValues.size()); |
| 575 | std::copy(vValues.begin(), vValues.end(), vSorted.begin()); |
| 576 | std::sort(vSorted.begin(), vSorted.end()); |
| 577 | } |
| 578 | |
| 579 | T median() const |
| 580 | { |
| 581 | int size = vSorted.size(); |
| 582 | assert(size>0); |
| 583 | if(size & 1) // Odd number of elements |
| 584 | { |
| 585 | return vSorted[size/2]; |
| 586 | } |
| 587 | else // Even number of elements |
| 588 | { |
| 589 | return (vSorted[size/2-1] + vSorted[size/2]) / 2; |
| 590 | } |
| 591 | } |
| 592 | }; |
| 593 | |
| 594 | |
| 595 | |
| 596 | |
| 597 | |
| 598 | |
| 599 | |
| 600 | |
| 601 | |
| 602 | |
| 603 | // Note: It turns out we might have been able to use boost::thread |
| 604 | // by using TerminateThread(boost::thread.native_handle(), 0); |
| 605 | inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false) |
| 606 | { |
| 607 | pthread_t hthread = 0; |
| 608 | int ret = pthread_create(&hthread, NULL, (void*(*)(void*))pfn, parg); |
| 609 | if (ret != 0) |
| 610 | { |
| 611 | printf("Error: pthread_create() returned %d\n", ret); |
| 612 | return (pthread_t)0; |
| 613 | } |
| 614 | if (!fWantHandle) |
| 615 | { |
| 616 | pthread_detach(hthread); |
| 617 | return (pthread_t)-1; |
| 618 | } |
| 619 | return hthread; |
| 620 | } |
| 621 | |
| 622 | #define THREAD_PRIORITY_LOWEST PRIO_MAX |
| 623 | #define THREAD_PRIORITY_BELOW_NORMAL 2 |
| 624 | #define THREAD_PRIORITY_NORMAL 0 |
| 625 | #define THREAD_PRIORITY_ABOVE_NORMAL 0 |
| 626 | |
| 627 | inline void SetThreadPriority(int nPriority) |
| 628 | { |
| 629 | // It's unclear if it's even possible to change thread priorities on Linux, |
| 630 | // but we really and truly need it for the generation threads. |
| 631 | #ifdef PRIO_THREAD |
| 632 | setpriority(PRIO_THREAD, 0, nPriority); |
| 633 | #else |
| 634 | setpriority(PRIO_PROCESS, 0, nPriority); |
| 635 | #endif |
| 636 | } |
| 637 | |
| 638 | inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode) |
| 639 | { |
| 640 | return (pthread_cancel(hthread) == 0); |
| 641 | } |
| 642 | |
| 643 | inline void ExitThread(size_t nExitCode) |
| 644 | { |
| 645 | pthread_exit((void*)nExitCode); |
| 646 | } |
| 647 | |
| 648 | |
| 649 | |
| 650 | inline bool AffinityBugWorkaround(void(*pfn)(void*)) |
| 651 | { |
| 652 | return false; |
| 653 | } |
| 654 | |
| 655 | inline uint32_t ByteReverse(uint32_t value) |
| 656 | { |
| 657 | value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); |
| 658 | return (value<<16) | (value>>16); |
| 659 | } |
| 660 | |
| 661 | #endif |