Browse Source

LoopForever and ThreadTrace helpers

miguelfreitas
Gavin Andresen 12 years ago
parent
commit
72f14d26ec
  1. 58
      src/test/util_tests.cpp
  2. 56
      src/util.h

58
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() BOOST_AUTO_TEST_SUITE_END()

56
src/util.h

@ -527,4 +527,60 @@ inline uint32_t ByteReverse(uint32_t value)
return (value<<16) | (value>>16); 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 #endif

Loading…
Cancel
Save