From 97e961a0486747526c5f0d5e1ee6c496cee12df7 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 19 Sep 2013 14:35:01 -0700 Subject: [PATCH] Add InterruptibleThread unit test --- .../beast_core/thread/InterruptibleThread.cpp | 73 +++++++++++++++++++ .../beast_core/thread/InterruptibleThread.h | 6 ++ .../beast_core/thread/ThreadWithCallQueue.cpp | 2 + 3 files changed, 81 insertions(+) diff --git a/src/beast/modules/beast_core/thread/InterruptibleThread.cpp b/src/beast/modules/beast_core/thread/InterruptibleThread.cpp index 3f3c233b3f..51ba7e783c 100644 --- a/src/beast/modules/beast_core/thread/InterruptibleThread.cpp +++ b/src/beast/modules/beast_core/thread/InterruptibleThread.cpp @@ -63,6 +63,9 @@ void InterruptibleThread::start (EntryPoint* const entryPoint) void InterruptibleThread::join () { + m_thread.signalThreadShouldExit(); + m_thread.notify(); + interrupt(); m_thread.stopThread (-1); } @@ -200,3 +203,73 @@ bool CurrentInterruptibleThread::interruptionPoint () return interrupted; } + +//------------------------------------------------------------------------------ + +class InterruptibleThreadTests : public UnitTest +{ +public: + enum + { + callsPerThread = 100000 + }; + + struct TestThread : InterruptibleThread::EntryPoint + { + explicit TestThread (int id) + : m_thread ("#" + String::fromNumber (id)) + { + m_thread.start (this); + } + + void threadRun () + { + while (! m_thread.peekThread().threadShouldExit()) + { + String s; + + while (!m_thread.interruptionPoint ()) + { + s = s + String::fromNumber (m_random.nextInt ()); + + if (s.length () > 100) + s = String::empty; + } + } + } + + Random m_random; + InterruptibleThread m_thread; + }; + + void testThreads (std::size_t nThreads) + { + beginTestCase (String::fromNumber (nThreads) + " threads"); + + OwnedArray threads; + threads.ensureStorageAllocated (nThreads); + + for (std::size_t i = 0; i < nThreads; ++i) + threads.add (new TestThread (i + 1)); + + for (std::size_t i = 0; i < callsPerThread * nThreads; ++i) + { + int const n (random().nextInt (threads.size())); + threads[n]->m_thread.interrupt(); + } + + pass (); + } + + void runTest () + { + testThreads (8); + testThreads (64); + } + + InterruptibleThreadTests () : UnitTest ("InterruptibleThread", "beast") + { + } +}; + +static InterruptibleThreadTests interruptibleThreadTests; diff --git a/src/beast/modules/beast_core/thread/InterruptibleThread.h b/src/beast/modules/beast_core/thread/InterruptibleThread.h index 658d486543..36b43c7dda 100644 --- a/src/beast/modules/beast_core/thread/InterruptibleThread.h +++ b/src/beast/modules/beast_core/thread/InterruptibleThread.h @@ -125,6 +125,12 @@ public: */ static InterruptibleThread* getCurrentThread (); + // private + Thread& peekThread () + { + return m_thread; + } + private: class ThreadHelper : public Thread { diff --git a/src/beast/modules/beast_core/thread/ThreadWithCallQueue.cpp b/src/beast/modules/beast_core/thread/ThreadWithCallQueue.cpp index 272e7c9e11..25ccffa7f5 100644 --- a/src/beast/modules/beast_core/thread/ThreadWithCallQueue.cpp +++ b/src/beast/modules/beast_core/thread/ThreadWithCallQueue.cpp @@ -259,10 +259,12 @@ public: } #endif +#if 1 for (int i = 0; i < threads.size(); ++i) threads[i]->stop (false); for (int i = 0; i < threads.size(); ++i) threads[i]->stop (true); +#endif pass (); }