]>
Commit | Line | Data |
---|---|---|
1f2e0df8 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
57702541 | 2 | // Copyright (c) 2009-2014 The Bitcoin developers |
1f2e0df8 | 3 | // Distributed under the MIT/X11 software license, see the accompanying |
3a25a2b9 | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
51ed9ec9 | 5 | |
1f2e0df8 WL |
6 | #ifndef BITCOIN_UTIL_H |
7 | #define BITCOIN_UTIL_H | |
8 | ||
51ed9ec9 BD |
9 | #if defined(HAVE_CONFIG_H) |
10 | #include "bitcoin-config.h" | |
11 | #endif | |
12 | ||
13 | #include "compat.h" | |
14 | #include "serialize.h" | |
b77dfdc9 | 15 | #include "tinyformat.h" |
1f2e0df8 | 16 | |
51ed9ec9 BD |
17 | #include <cstdio> |
18 | #include <exception> | |
51ed9ec9 | 19 | #include <map> |
65ec9eab | 20 | #include <stdarg.h> |
51ed9ec9 BD |
21 | #include <stdint.h> |
22 | #include <string> | |
23 | #include <utility> | |
24 | #include <vector> | |
65ec9eab | 25 | |
6853e627 | 26 | #ifndef WIN32 |
6644d98d | 27 | #include <sys/resource.h> |
51ed9ec9 BD |
28 | #include <sys/time.h> |
29 | #include <sys/types.h> | |
85663f2c | 30 | #endif |
1f2e0df8 | 31 | |
ee12c3d6 | 32 | #include <boost/filesystem/path.hpp> |
51ed9ec9 | 33 | #include <boost/thread.hpp> |
1f2e0df8 | 34 | |
51ed9ec9 BD |
35 | class CNetAddr; |
36 | class uint256; | |
bde280b9 | 37 | |
51ed9ec9 BD |
38 | static const int64_t COIN = 100000000; |
39 | static const int64_t CENT = 1000000; | |
ed6d0b5f | 40 | |
1f2e0df8 WL |
41 | #define BEGIN(a) ((char*)&(a)) |
42 | #define END(a) ((char*)&((&(a))[1])) | |
43 | #define UBEGIN(a) ((unsigned char*)&(a)) | |
44 | #define UEND(a) ((unsigned char*)&((&(a))[1])) | |
45 | #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) | |
1f2e0df8 | 46 | |
d5f1e727 WL |
47 | /* Format characters for (s)size_t, ptrdiff_t, uint64_t. |
48 | * | |
49 | * As the tinyformat-based formatting system is type-safe, no special format | |
50 | * characters are really needed to specify sizes. Tinyformat can support | |
51 | * (ignores) the C99 prefixes such as "ll" but chokes on MSVC's inttypes | |
52 | * defines prefixes such as "I64X". So don't include inttypes.h and define our | |
53 | * own for compatibility. | |
54 | * If you get a warning here about a redefine of PRI?64, make sure that | |
55 | * inttypes.h is not included. | |
56 | */ | |
57 | #define PRIszx "x" | |
58 | #define PRIszu "u" | |
59 | #define PRIszd "d" | |
60 | #define PRIpdx "x" | |
61 | #define PRIpdu "u" | |
62 | #define PRIpdd "d" | |
63 | #define PRIx64 "x" | |
64 | #define PRIu64 "u" | |
65 | #define PRId64 "d" | |
51ed9ec9 | 66 | |
1f2e0df8 | 67 | // This is needed because the foreach macro can't get over the comma in pair<t1, t2> |
9aef9bca | 68 | #define PAIRTYPE(t1, t2) std::pair<t1, t2> |
1f2e0df8 | 69 | |
1f2e0df8 WL |
70 | // Align by increasing pointer, must have extra space at end of buffer |
71 | template <size_t nBytes, typename T> | |
72 | T* alignup(T* p) | |
73 | { | |
74 | union | |
75 | { | |
76 | T* ptr; | |
77 | size_t n; | |
78 | } u; | |
79 | u.ptr = p; | |
80 | u.n = (u.n + (nBytes-1)) & ~(nBytes-1); | |
81 | return u.ptr; | |
82 | } | |
83 | ||
6853e627 | 84 | #ifdef WIN32 |
1f2e0df8 | 85 | #define MSG_DONTWAIT 0 |
26ce92b3 | 86 | |
1f2e0df8 WL |
87 | #ifndef S_IRUSR |
88 | #define S_IRUSR 0400 | |
89 | #define S_IWUSR 0200 | |
90 | #endif | |
1f2e0df8 | 91 | #else |
1f2e0df8 | 92 | #define MAX_PATH 1024 |
1b43bf0d | 93 | #endif |
93714039 | 94 | // As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0 |
51ed9ec9 | 95 | #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) |
93714039 | 96 | #define MSG_NOSIGNAL 0 |
97 | #endif | |
1b43bf0d | 98 | |
51ed9ec9 | 99 | inline void MilliSleep(int64_t n) |
1f2e0df8 | 100 | { |
e2654c8d | 101 | // Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50 |
102 | // until fixed in 1.52. Use the deprecated sleep method for the broken case. | |
103 | // See: https://svn.boost.org/trac/boost/ticket/7238 | |
35b8af92 | 104 | #if defined(HAVE_WORKING_BOOST_SLEEP_FOR) |
1b43bf0d | 105 | boost::this_thread::sleep_for(boost::chrono::milliseconds(n)); |
35b8af92 | 106 | #elif defined(HAVE_WORKING_BOOST_SLEEP) |
1b43bf0d | 107 | boost::this_thread::sleep(boost::posix_time::milliseconds(n)); |
35b8af92 | 108 | #else |
cd696e64 | 109 | //should never get here |
35b8af92 | 110 | #error missing boost sleep implementation |
1f2e0df8 | 111 | #endif |
1b43bf0d | 112 | } |
1f2e0df8 | 113 | |
1f2e0df8 WL |
114 | |
115 | ||
116 | extern std::map<std::string, std::string> mapArgs; | |
117 | extern std::map<std::string, std::vector<std::string> > mapMultiArgs; | |
118 | extern bool fDebug; | |
119 | extern bool fPrintToConsole; | |
9e9056cd | 120 | extern bool fPrintToDebugLog; |
1f2e0df8 | 121 | extern bool fServer; |
1f2e0df8 | 122 | extern std::string strMiscWarning; |
1f2e0df8 WL |
123 | extern bool fNoListen; |
124 | extern bool fLogTimestamps; | |
ee337423 | 125 | extern volatile bool fReopenDebugLog; |
1f2e0df8 WL |
126 | |
127 | void RandAddSeed(); | |
128 | void RandAddSeedPerfmon(); | |
e51321fb | 129 | |
b77dfdc9 WL |
130 | /* Return true if log accepts specified category */ |
131 | bool LogAcceptCategory(const char* category); | |
132 | /* Send a string to the log output */ | |
133 | int LogPrintStr(const std::string &str); | |
134 | ||
135 | #define strprintf tfm::format | |
881a85a2 | 136 | #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) |
52d3a481 | 137 | |
b77dfdc9 WL |
138 | /* When we switch to C++11, this can be switched to variadic templates instead |
139 | * of this macro-based construction (see tinyformat.h). | |
b0a90fbb | 140 | */ |
b77dfdc9 WL |
141 | #define MAKE_ERROR_AND_LOG_FUNC(n) \ |
142 | /* Print to debug.log if -debug=category switch is given OR category is NULL. */ \ | |
143 | template<TINYFORMAT_ARGTYPES(n)> \ | |
144 | static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ | |
145 | { \ | |
146 | if(!LogAcceptCategory(category)) return 0; \ | |
147 | return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ | |
148 | } \ | |
149 | /* Log error and return false */ \ | |
150 | template<TINYFORMAT_ARGTYPES(n)> \ | |
151 | static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ | |
152 | { \ | |
2383e488 | 153 | LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ |
b77dfdc9 WL |
154 | return false; \ |
155 | } | |
156 | ||
157 | TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) | |
158 | ||
159 | /* Zero-arg versions of logging and error, these are not covered by | |
160 | * TINYFORMAT_FOREACH_ARGNUM | |
161 | */ | |
162 | static inline int LogPrint(const char* category, const char* format) | |
163 | { | |
164 | if(!LogAcceptCategory(category)) return 0; | |
165 | return LogPrintStr(format); | |
166 | } | |
167 | static inline bool error(const char* format) | |
168 | { | |
2383e488 | 169 | LogPrintStr(std::string("ERROR: ") + format + "\n"); |
b77dfdc9 WL |
170 | return false; |
171 | } | |
b0a90fbb | 172 | |
bcc292b2 | 173 | |
1f2e0df8 WL |
174 | void LogException(std::exception* pex, const char* pszThread); |
175 | void PrintException(std::exception* pex, const char* pszThread); | |
176 | void PrintExceptionContinue(std::exception* pex, const char* pszThread); | |
177 | void ParseString(const std::string& str, char c, std::vector<std::string>& v); | |
51ed9ec9 BD |
178 | std::string FormatMoney(int64_t n, bool fPlus=false); |
179 | bool ParseMoney(const std::string& str, int64_t& nRet); | |
180 | bool ParseMoney(const char* pszIn, int64_t& nRet); | |
17faf562 | 181 | std::string SanitizeString(const std::string& str); |
1f2e0df8 WL |
182 | std::vector<unsigned char> ParseHex(const char* psz); |
183 | std::vector<unsigned char> ParseHex(const std::string& str); | |
922e8e29 | 184 | bool IsHex(const std::string& str); |
4b603f1c PW |
185 | std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL); |
186 | std::string DecodeBase64(const std::string& str); | |
187 | std::string EncodeBase64(const unsigned char* pch, size_t len); | |
188 | std::string EncodeBase64(const std::string& str); | |
c4c99ade PW |
189 | std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL); |
190 | std::string DecodeBase32(const std::string& str); | |
191 | std::string EncodeBase32(const unsigned char* pch, size_t len); | |
192 | std::string EncodeBase32(const std::string& str); | |
3ae07355 | 193 | void ParseParameters(int argc, const char*const argv[]); |
1f2e0df8 WL |
194 | bool WildcardMatch(const char* psz, const char* mask); |
195 | bool WildcardMatch(const std::string& str, const std::string& mask); | |
768e5d52 | 196 | void FileCommit(FILE *fileout); |
1f2e0df8 | 197 | int GetFilesize(FILE* file); |
1eb57879 | 198 | bool TruncateFile(FILE *file, unsigned int length); |
ba29a559 | 199 | int RaiseFileDescriptorLimit(int nMinFD); |
bba89aa8 | 200 | void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); |
768e5d52 | 201 | bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); |
ee12c3d6 PW |
202 | boost::filesystem::path GetDefaultDataDir(); |
203 | const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); | |
204 | boost::filesystem::path GetConfigFile(); | |
205 | boost::filesystem::path GetPidFile(); | |
a034c7eb | 206 | #ifndef WIN32 |
ee12c3d6 | 207 | void CreatePidFile(const boost::filesystem::path &path, pid_t pid); |
a034c7eb | 208 | #endif |
f4203de3 | 209 | void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); |
3e468840 PK |
210 | #ifdef WIN32 |
211 | boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); | |
212 | #endif | |
597fa4cd | 213 | boost::filesystem::path GetTempPath(); |
1f2e0df8 WL |
214 | void ShrinkDebugFile(); |
215 | int GetRandInt(int nMax); | |
51ed9ec9 | 216 | uint64_t GetRand(uint64_t nMax); |
f718aedd | 217 | uint256 GetRandHash(); |
51ed9ec9 BD |
218 | int64_t GetTime(); |
219 | void SetMockTime(int64_t nMockTimeIn); | |
220 | int64_t GetAdjustedTime(); | |
221 | int64_t GetTimeOffset(); | |
1f2e0df8 | 222 | std::string FormatFullVersion(); |
f8ded588 | 223 | std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments); |
51ed9ec9 | 224 | void AddTimeData(const CNetAddr& ip, int64_t nTime); |
429039d4 | 225 | void runCommand(std::string strCommand); |
1f2e0df8 WL |
226 | |
227 | ||
228 | ||
229 | ||
230 | ||
231 | ||
232 | ||
233 | ||
234 | ||
51ed9ec9 | 235 | inline std::string i64tostr(int64_t n) |
1f2e0df8 | 236 | { |
51ed9ec9 | 237 | return strprintf("%"PRId64, n); |
1f2e0df8 WL |
238 | } |
239 | ||
240 | inline std::string itostr(int n) | |
241 | { | |
242 | return strprintf("%d", n); | |
243 | } | |
244 | ||
51ed9ec9 | 245 | inline int64_t atoi64(const char* psz) |
1f2e0df8 WL |
246 | { |
247 | #ifdef _MSC_VER | |
248 | return _atoi64(psz); | |
249 | #else | |
250 | return strtoll(psz, NULL, 10); | |
251 | #endif | |
252 | } | |
253 | ||
51ed9ec9 | 254 | inline int64_t atoi64(const std::string& str) |
1f2e0df8 WL |
255 | { |
256 | #ifdef _MSC_VER | |
257 | return _atoi64(str.c_str()); | |
258 | #else | |
259 | return strtoll(str.c_str(), NULL, 10); | |
260 | #endif | |
261 | } | |
262 | ||
263 | inline int atoi(const std::string& str) | |
264 | { | |
265 | return atoi(str.c_str()); | |
266 | } | |
267 | ||
268 | inline int roundint(double d) | |
269 | { | |
270 | return (int)(d > 0 ? d + 0.5 : d - 0.5); | |
271 | } | |
272 | ||
51ed9ec9 | 273 | inline int64_t roundint64(double d) |
1f2e0df8 | 274 | { |
51ed9ec9 | 275 | return (int64_t)(d > 0 ? d + 0.5 : d - 0.5); |
1f2e0df8 WL |
276 | } |
277 | ||
51ed9ec9 | 278 | inline int64_t abs64(int64_t n) |
1f2e0df8 WL |
279 | { |
280 | return (n >= 0 ? n : -n); | |
281 | } | |
282 | ||
283 | template<typename T> | |
284 | std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) | |
285 | { | |
ac4e7f62 WL |
286 | std::string rv; |
287 | static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', | |
288 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | |
88dc2d6c WL |
289 | rv.reserve((itend-itbegin)*3); |
290 | for(T it = itbegin; it < itend; ++it) | |
291 | { | |
292 | unsigned char val = (unsigned char)(*it); | |
293 | if(fSpaces && it != itbegin) | |
294 | rv.push_back(' '); | |
295 | rv.push_back(hexmap[val>>4]); | |
296 | rv.push_back(hexmap[val&15]); | |
297 | } | |
298 | ||
ac4e7f62 | 299 | return rv; |
1f2e0df8 WL |
300 | } |
301 | ||
5d891489 PW |
302 | template<typename T> |
303 | inline std::string HexStr(const T& vch, bool fSpaces=false) | |
1f2e0df8 WL |
304 | { |
305 | return HexStr(vch.begin(), vch.end(), fSpaces); | |
306 | } | |
307 | ||
1f2e0df8 WL |
308 | template<typename T> |
309 | void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true) | |
310 | { | |
881a85a2 | 311 | LogPrintf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str()); |
1f2e0df8 WL |
312 | } |
313 | ||
314 | inline void PrintHex(const std::vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true) | |
315 | { | |
881a85a2 | 316 | LogPrintf(pszFormat, HexStr(vch, fSpaces).c_str()); |
1f2e0df8 WL |
317 | } |
318 | ||
51ed9ec9 | 319 | inline int64_t GetPerformanceCounter() |
1f2e0df8 | 320 | { |
51ed9ec9 | 321 | int64_t nCounter = 0; |
6853e627 | 322 | #ifdef WIN32 |
1f2e0df8 WL |
323 | QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); |
324 | #else | |
325 | timeval t; | |
326 | gettimeofday(&t, NULL); | |
51ed9ec9 | 327 | nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; |
1f2e0df8 WL |
328 | #endif |
329 | return nCounter; | |
330 | } | |
331 | ||
51ed9ec9 | 332 | inline int64_t GetTimeMillis() |
1f2e0df8 WL |
333 | { |
334 | return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) - | |
335 | boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds(); | |
336 | } | |
337 | ||
51ed9ec9 | 338 | inline int64_t GetTimeMicros() |
0ae0712b PW |
339 | { |
340 | return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) - | |
341 | boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds(); | |
342 | } | |
343 | ||
51ed9ec9 | 344 | inline std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) |
1f2e0df8 WL |
345 | { |
346 | time_t n = nTime; | |
347 | struct tm* ptmTime = gmtime(&n); | |
348 | char pszTime[200]; | |
349 | strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime); | |
350 | return pszTime; | |
351 | } | |
352 | ||
353 | template<typename T> | |
354 | void skipspaces(T& it) | |
355 | { | |
356 | while (isspace(*it)) | |
357 | ++it; | |
358 | } | |
359 | ||
360 | inline bool IsSwitchChar(char c) | |
361 | { | |
6853e627 | 362 | #ifdef WIN32 |
1f2e0df8 WL |
363 | return c == '-' || c == '/'; |
364 | #else | |
365 | return c == '-'; | |
366 | #endif | |
367 | } | |
368 | ||
3ae07355 GA |
369 | /** |
370 | * Return string argument or default value | |
371 | * | |
372 | * @param strArg Argument to get (e.g. "-foo") | |
373 | * @param default (e.g. "1") | |
374 | * @return command-line argument or default value | |
375 | */ | |
376 | std::string GetArg(const std::string& strArg, const std::string& strDefault); | |
1f2e0df8 | 377 | |
3ae07355 GA |
378 | /** |
379 | * Return integer argument or default value | |
380 | * | |
381 | * @param strArg Argument to get (e.g. "-foo") | |
382 | * @param default (e.g. 1) | |
383 | * @return command-line argument (0 if invalid number) or default value | |
384 | */ | |
51ed9ec9 | 385 | int64_t GetArg(const std::string& strArg, int64_t nDefault); |
1f2e0df8 | 386 | |
3ae07355 GA |
387 | /** |
388 | * Return boolean argument or default value | |
389 | * | |
390 | * @param strArg Argument to get (e.g. "-foo") | |
391 | * @param default (true or false) | |
392 | * @return command-line argument or default value | |
393 | */ | |
3260b4c0 | 394 | bool GetBoolArg(const std::string& strArg, bool fDefault); |
1f2e0df8 | 395 | |
0fcf91ea GA |
396 | /** |
397 | * Set an argument if it doesn't already have a value | |
398 | * | |
399 | * @param strArg Argument to set (e.g. "-foo") | |
400 | * @param strValue Value (e.g. "1") | |
401 | * @return true if argument gets set, false if it already had a value | |
402 | */ | |
403 | bool SoftSetArg(const std::string& strArg, const std::string& strValue); | |
404 | ||
405 | /** | |
406 | * Set a boolean argument if it doesn't already have a value | |
407 | * | |
408 | * @param strArg Argument to set (e.g. "-foo") | |
409 | * @param fValue Value (e.g. false) | |
410 | * @return true if argument gets set, false if it already had a value | |
411 | */ | |
7bf8b7c2 | 412 | bool SoftSetBoolArg(const std::string& strArg, bool fValue); |
1f2e0df8 | 413 | |
907a2aa4 GM |
414 | /** |
415 | * MWC RNG of George Marsaglia | |
416 | * This is intended to be fast. It has a period of 2^59.3, though the | |
417 | * least significant 16 bits only have a period of about 2^30.1. | |
418 | * | |
419 | * @return random value | |
420 | */ | |
421 | extern uint32_t insecure_rand_Rz; | |
422 | extern uint32_t insecure_rand_Rw; | |
423 | static inline uint32_t insecure_rand(void) | |
424 | { | |
b001c871 PK |
425 | insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); |
426 | insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); | |
427 | return (insecure_rand_Rw << 16) + insecure_rand_Rz; | |
907a2aa4 | 428 | } |
1f2e0df8 | 429 | |
907a2aa4 GM |
430 | /** |
431 | * Seed insecure_rand using the random pool. | |
432 | * @param Deterministic Use a determinstic seed | |
433 | */ | |
434 | void seed_insecure_rand(bool fDeterministic=false); | |
1f2e0df8 | 435 | |
42656ea2 GA |
436 | /** |
437 | * Timing-attack-resistant comparison. | |
438 | * Takes time proportional to length | |
439 | * of first argument. | |
440 | */ | |
441 | template <typename T> | |
442 | bool TimingResistantEqual(const T& a, const T& b) | |
443 | { | |
444 | if (b.size() == 0) return a.size() == 0; | |
445 | size_t accumulator = a.size() ^ b.size(); | |
446 | for (size_t i = 0; i < a.size(); i++) | |
447 | accumulator |= a[i] ^ b[i%b.size()]; | |
448 | return accumulator == 0; | |
449 | } | |
450 | ||
ea0796bd | 451 | /** Median filter over a stream of values. |
6b8de05d PW |
452 | * Returns the median of the last N numbers |
453 | */ | |
a8b95ce6 WL |
454 | template <typename T> class CMedianFilter |
455 | { | |
456 | private: | |
457 | std::vector<T> vValues; | |
458 | std::vector<T> vSorted; | |
735a6069 | 459 | unsigned int nSize; |
a8b95ce6 | 460 | public: |
735a6069 | 461 | CMedianFilter(unsigned int size, T initial_value): |
a8b95ce6 WL |
462 | nSize(size) |
463 | { | |
464 | vValues.reserve(size); | |
465 | vValues.push_back(initial_value); | |
466 | vSorted = vValues; | |
467 | } | |
ea0796bd | 468 | |
a8b95ce6 WL |
469 | void input(T value) |
470 | { | |
471 | if(vValues.size() == nSize) | |
472 | { | |
473 | vValues.erase(vValues.begin()); | |
474 | } | |
475 | vValues.push_back(value); | |
476 | ||
477 | vSorted.resize(vValues.size()); | |
478 | std::copy(vValues.begin(), vValues.end(), vSorted.begin()); | |
479 | std::sort(vSorted.begin(), vSorted.end()); | |
480 | } | |
481 | ||
482 | T median() const | |
483 | { | |
484 | int size = vSorted.size(); | |
20091df7 | 485 | assert(size>0); |
a8b95ce6 WL |
486 | if(size & 1) // Odd number of elements |
487 | { | |
488 | return vSorted[size/2]; | |
489 | } | |
490 | else // Even number of elements | |
491 | { | |
492 | return (vSorted[size/2-1] + vSorted[size/2]) / 2; | |
493 | } | |
494 | } | |
1c4aab92 MH |
495 | |
496 | int size() const | |
497 | { | |
498 | return vValues.size(); | |
499 | } | |
500 | ||
501 | std::vector<T> sorted () const | |
502 | { | |
503 | return vSorted; | |
504 | } | |
a8b95ce6 WL |
505 | }; |
506 | ||
6853e627 | 507 | #ifdef WIN32 |
1f2e0df8 WL |
508 | inline void SetThreadPriority(int nPriority) |
509 | { | |
510 | SetThreadPriority(GetCurrentThread(), nPriority); | |
511 | } | |
512 | #else | |
1f2e0df8 | 513 | |
93714039 | 514 | // PRIO_MAX is not defined on Solaris |
515 | #ifndef PRIO_MAX | |
d78900cc | 516 | #define PRIO_MAX 20 |
93714039 | 517 | #endif |
1f2e0df8 WL |
518 | #define THREAD_PRIORITY_LOWEST PRIO_MAX |
519 | #define THREAD_PRIORITY_BELOW_NORMAL 2 | |
520 | #define THREAD_PRIORITY_NORMAL 0 | |
53e71135 | 521 | #define THREAD_PRIORITY_ABOVE_NORMAL (-2) |
1f2e0df8 WL |
522 | |
523 | inline void SetThreadPriority(int nPriority) | |
524 | { | |
525 | // It's unclear if it's even possible to change thread priorities on Linux, | |
526 | // but we really and truly need it for the generation threads. | |
527 | #ifdef PRIO_THREAD | |
528 | setpriority(PRIO_THREAD, 0, nPriority); | |
529 | #else | |
530 | setpriority(PRIO_PROCESS, 0, nPriority); | |
531 | #endif | |
532 | } | |
1f2e0df8 WL |
533 | #endif |
534 | ||
96931d6f | 535 | void RenameThread(const char* name); |
1f2e0df8 | 536 | |
6ccff2cb NS |
537 | inline uint32_t ByteReverse(uint32_t value) |
538 | { | |
b985efaa LR |
539 | value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); |
540 | return (value<<16) | (value>>16); | |
6ccff2cb NS |
541 | } |
542 | ||
72f14d26 GA |
543 | // Standard wrapper for do-something-forever thread functions. |
544 | // "Forever" really means until the thread is interrupted. | |
545 | // Use it like: | |
c43da3f1 | 546 | // new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000)); |
72f14d26 GA |
547 | // or maybe: |
548 | // boost::function<void()> f = boost::bind(&FunctionWithArg, argument); | |
549 | // threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds)); | |
51ed9ec9 | 550 | template <typename Callable> void LoopForever(const char* name, Callable func, int64_t msecs) |
72f14d26 GA |
551 | { |
552 | std::string s = strprintf("bitcoin-%s", name); | |
553 | RenameThread(s.c_str()); | |
881a85a2 | 554 | LogPrintf("%s thread start\n", name); |
72f14d26 GA |
555 | try |
556 | { | |
557 | while (1) | |
558 | { | |
72f14d26 | 559 | MilliSleep(msecs); |
c43da3f1 | 560 | func(); |
72f14d26 GA |
561 | } |
562 | } | |
563 | catch (boost::thread_interrupted) | |
564 | { | |
881a85a2 | 565 | LogPrintf("%s thread stop\n", name); |
72f14d26 GA |
566 | throw; |
567 | } | |
568 | catch (std::exception& e) { | |
569 | PrintException(&e, name); | |
570 | } | |
571 | catch (...) { | |
572 | PrintException(NULL, name); | |
573 | } | |
574 | } | |
575 | // .. and a wrapper that just calls func once | |
576 | template <typename Callable> void TraceThread(const char* name, Callable func) | |
577 | { | |
578 | std::string s = strprintf("bitcoin-%s", name); | |
579 | RenameThread(s.c_str()); | |
580 | try | |
581 | { | |
881a85a2 | 582 | LogPrintf("%s thread start\n", name); |
72f14d26 | 583 | func(); |
881a85a2 | 584 | LogPrintf("%s thread exit\n", name); |
72f14d26 GA |
585 | } |
586 | catch (boost::thread_interrupted) | |
587 | { | |
881a85a2 | 588 | LogPrintf("%s thread interrupt\n", name); |
72f14d26 GA |
589 | throw; |
590 | } | |
591 | catch (std::exception& e) { | |
592 | PrintException(&e, name); | |
593 | } | |
594 | catch (...) { | |
595 | PrintException(NULL, name); | |
596 | } | |
597 | } | |
598 | ||
1f2e0df8 | 599 | #endif |