diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2013-03-08 20:19:17 -0500 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2013-04-03 19:57:13 -0400 |
commit | 72f14d26ecc67a210a29d7914e580b8e67e45d8e (patch) | |
tree | a5c32b1a0b4690be8de680e1629a7d5d543dbaf0 | |
parent | 1b43bf0d3ae7b1fcde0c0e20c23c341540f4c8d2 (diff) |
LoopForever and ThreadTrace helpers
-rw-r--r-- | src/test/util_tests.cpp | 58 | ||||
-rw-r--r-- | src/util.h | 56 |
2 files changed, 114 insertions, 0 deletions
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 1b0ccad511..2d05794cc7 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -323,4 +323,62 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) } } +static int nCounter = 0; + +static void Count() +{ + ++nCounter; + MilliSleep(10); +} + +static void CountWithArg(int arg) +{ + nCounter += arg; + MilliSleep(10); +} + +BOOST_AUTO_TEST_CASE(util_loop_forever1) +{ + boost::thread_group threadGroup; + + threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "count", &Count, 1)); + MilliSleep(1); + threadGroup.interrupt_all(); + BOOST_CHECK_EQUAL(nCounter, 1); + nCounter = 0; +} + +BOOST_AUTO_TEST_CASE(util_loop_forever2) +{ + boost::thread_group threadGroup; + + boost::function<void()> f = boost::bind(&CountWithArg, 11); + threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "count11", f, 11)); + MilliSleep(1); + threadGroup.interrupt_all(); + BOOST_CHECK_EQUAL(nCounter, 11); + nCounter = 0; +} + +BOOST_AUTO_TEST_CASE(util_threadtrace1) +{ + boost::thread_group threadGroup; + + threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "count11", &Count)); + threadGroup.join_all(); + BOOST_CHECK_EQUAL(nCounter, 1); + nCounter = 0; +} + +BOOST_AUTO_TEST_CASE(util_threadtrace2) +{ + boost::thread_group threadGroup; + + boost::function<void()> f = boost::bind(&CountWithArg, 11); + threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "count11", f)); + threadGroup.join_all(); + BOOST_CHECK_EQUAL(nCounter, 11); + nCounter = 0; +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.h b/src/util.h index 5173686eda..0c5ed91634 100644 --- a/src/util.h +++ b/src/util.h @@ -527,4 +527,60 @@ inline uint32_t ByteReverse(uint32_t value) return (value<<16) | (value>>16); } +// Standard wrapper for do-something-forever thread functions. +// "Forever" really means until the thread is interrupted. +// Use it like: +// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000)); +// or maybe: +// boost::function<void()> f = boost::bind(&FunctionWithArg, argument); +// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds)); +template <typename Callable> void LoopForever(const char* name, Callable func, int64 msecs) +{ + std::string s = strprintf("bitcoin-%s", name); + RenameThread(s.c_str()); + printf("%s thread start\n", name); + try + { + while (1) + { + func(); + MilliSleep(msecs); + } + } + catch (boost::thread_interrupted) + { + printf("%s thread stop\n", name); + throw; + } + catch (std::exception& e) { + PrintException(&e, name); + } + catch (...) { + PrintException(NULL, name); + } +} +// .. and a wrapper that just calls func once +template <typename Callable> void TraceThread(const char* name, Callable func) +{ + std::string s = strprintf("bitcoin-%s", name); + RenameThread(s.c_str()); + try + { + printf("%s thread start\n", name); + func(); + printf("%s thread exit\n", name); + } + catch (boost::thread_interrupted) + { + printf("%s thread interrupt\n", name); + throw; + } + catch (std::exception& e) { + PrintException(&e, name); + } + catch (...) { + PrintException(NULL, name); + } +} + #endif |