move code testing wxThread classes from the console sample to a new CppUnit test

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64283 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2010-05-10 21:48:24 +00:00
parent 0fe260084e
commit 1f5496a0f5
12 changed files with 459 additions and 442 deletions

View File

@@ -132,7 +132,6 @@
#define TEST_STDPATHS
#define TEST_STREAMS
#define TEST_TEXTSTREAM
#define TEST_THREADS
#define TEST_TIMER
// #define TEST_VOLUME --FIXME! (RN)
#define TEST_WCHAR
@@ -3486,403 +3485,6 @@ static void TestTextInputStream()
#endif // TEST_TEXTSTREAM
// ----------------------------------------------------------------------------
// threads
// ----------------------------------------------------------------------------
#ifdef TEST_THREADS
#include "wx/thread.h"
static size_t gs_counter = (size_t)-1;
static wxCriticalSection gs_critsect;
static wxSemaphore gs_cond;
class MyJoinableThread : public wxThread
{
public:
MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
{ m_n = n; Create(); }
// thread execution starts here
virtual ExitCode Entry();
private:
size_t m_n;
};
wxThread::ExitCode MyJoinableThread::Entry()
{
unsigned long res = 1;
for ( size_t n = 1; n < m_n; n++ )
{
res *= n;
// it's a loooong calculation :-)
Sleep(100);
}
return (ExitCode)res;
}
class MyDetachedThread : public wxThread
{
public:
MyDetachedThread(size_t n, wxChar ch)
{
m_n = n;
m_ch = ch;
m_cancelled = false;
Create();
}
// thread execution starts here
virtual ExitCode Entry();
// and stops here
virtual void OnExit();
private:
size_t m_n; // number of characters to write
wxChar m_ch; // character to write
bool m_cancelled; // false if we exit normally
};
wxThread::ExitCode MyDetachedThread::Entry()
{
{
wxCriticalSectionLocker lock(gs_critsect);
if ( gs_counter == (size_t)-1 )
gs_counter = 1;
else
gs_counter++;
}
for ( size_t n = 0; n < m_n; n++ )
{
if ( TestDestroy() )
{
m_cancelled = true;
break;
}
wxPutchar(m_ch);
fflush(stdout);
wxThread::Sleep(100);
}
return 0;
}
void MyDetachedThread::OnExit()
{
wxLogTrace(wxT("thread"), wxT("Thread %ld is in OnExit"), GetId());
wxCriticalSectionLocker lock(gs_critsect);
if ( !--gs_counter && !m_cancelled )
gs_cond.Post();
}
static void TestDetachedThreads()
{
wxPuts(wxT("\n*** Testing detached threads ***"));
static const size_t nThreads = 3;
MyDetachedThread *threads[nThreads];
size_t n;
for ( n = 0; n < nThreads; n++ )
{
threads[n] = new MyDetachedThread(10, 'A' + n);
}
threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
for ( n = 0; n < nThreads; n++ )
{
threads[n]->Run();
}
// wait until all threads terminate
gs_cond.Wait();
wxPuts(wxEmptyString);
}
static void TestJoinableThreads()
{
wxPuts(wxT("\n*** Testing a joinable thread (a loooong calculation...) ***"));
// calc 10! in the background
MyJoinableThread thread(10);
thread.Run();
wxPrintf(wxT("\nThread terminated with exit code %lu.\n"),
(unsigned long)thread.Wait());
}
static void TestThreadSuspend()
{
wxPuts(wxT("\n*** Testing thread suspend/resume functions ***"));
MyDetachedThread *thread = new MyDetachedThread(15, 'X');
thread->Run();
// this is for this demo only, in a real life program we'd use another
// condition variable which would be signaled from wxThread::Entry() to
// tell us that the thread really started running - but here just wait a
// bit and hope that it will be enough (the problem is, of course, that
// the thread might still not run when we call Pause() which will result
// in an error)
wxThread::Sleep(300);
for ( size_t n = 0; n < 3; n++ )
{
thread->Pause();
wxPuts(wxT("\nThread suspended"));
if ( n > 0 )
{
// don't sleep but resume immediately the first time
wxThread::Sleep(300);
}
wxPuts(wxT("Going to resume the thread"));
thread->Resume();
}
wxPuts(wxT("Waiting until it terminates now"));
// wait until the thread terminates
gs_cond.Wait();
wxPuts(wxEmptyString);
}
static void TestThreadDelete()
{
// As above, using Sleep() is only for testing here - we must use some
// synchronisation object instead to ensure that the thread is still
// running when we delete it - deleting a detached thread which already
// terminated will lead to a crash!
wxPuts(wxT("\n*** Testing thread delete function ***"));
MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
thread0->Delete();
wxPuts(wxT("\nDeleted a thread which didn't start to run yet."));
MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
thread1->Run();
wxThread::Sleep(300);
thread1->Delete();
wxPuts(wxT("\nDeleted a running thread."));
MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
thread2->Run();
wxThread::Sleep(300);
thread2->Pause();
thread2->Delete();
wxPuts(wxT("\nDeleted a sleeping thread."));
MyJoinableThread thread3(20);
thread3.Run();
thread3.Delete();
wxPuts(wxT("\nDeleted a joinable thread."));
MyJoinableThread thread4(2);
thread4.Run();
wxThread::Sleep(300);
thread4.Delete();
wxPuts(wxT("\nDeleted a joinable thread which already terminated."));
wxPuts(wxEmptyString);
}
class MyWaitingThread : public wxThread
{
public:
MyWaitingThread( wxMutex *mutex, wxCondition *condition )
{
m_mutex = mutex;
m_condition = condition;
Create();
}
virtual ExitCode Entry()
{
wxPrintf(wxT("Thread %lu has started running.\n"), GetId());
fflush(stdout);
gs_cond.Post();
wxPrintf(wxT("Thread %lu starts to wait...\n"), GetId());
fflush(stdout);
m_mutex->Lock();
m_condition->Wait();
m_mutex->Unlock();
wxPrintf(wxT("Thread %lu finished to wait, exiting.\n"), GetId());
fflush(stdout);
return 0;
}
private:
wxMutex *m_mutex;
wxCondition *m_condition;
};
static void TestThreadConditions()
{
wxMutex mutex;
wxCondition condition(mutex);
// otherwise its difficult to understand which log messages pertain to
// which condition
//wxLogTrace(wxT("thread"), wxT("Local condition var is %08x, gs_cond = %08x"),
// condition.GetId(), gs_cond.GetId());
// create and launch threads
MyWaitingThread *threads[10];
size_t n;
for ( n = 0; n < WXSIZEOF(threads); n++ )
{
threads[n] = new MyWaitingThread( &mutex, &condition );
}
for ( n = 0; n < WXSIZEOF(threads); n++ )
{
threads[n]->Run();
}
// wait until all threads run
wxPuts(wxT("Main thread is waiting for the other threads to start"));
fflush(stdout);
size_t nRunning = 0;
while ( nRunning < WXSIZEOF(threads) )
{
gs_cond.Wait();
nRunning++;
wxPrintf(wxT("Main thread: %u already running\n"), nRunning);
fflush(stdout);
}
wxPuts(wxT("Main thread: all threads started up."));
fflush(stdout);
wxThread::Sleep(500);
#if 1
// now wake one of them up
wxPrintf(wxT("Main thread: about to signal the condition.\n"));
fflush(stdout);
condition.Signal();
#endif
wxThread::Sleep(200);
// wake all the (remaining) threads up, so that they can exit
wxPrintf(wxT("Main thread: about to broadcast the condition.\n"));
fflush(stdout);
condition.Broadcast();
// give them time to terminate (dirty!)
wxThread::Sleep(500);
}
// semaphore tests
#include "wx/datetime.h"
class MySemaphoreThread : public wxThread
{
public:
MySemaphoreThread(int i, wxSemaphore *sem)
: wxThread(wxTHREAD_JOINABLE),
m_sem(sem),
m_i(i)
{
Create();
}
virtual ExitCode Entry()
{
wxPrintf(wxT("%s: Thread #%d (%ld) starting to wait for semaphore...\n"),
wxDateTime::Now().FormatTime().c_str(), m_i, (long)GetId());
m_sem->Wait();
wxPrintf(wxT("%s: Thread #%d (%ld) acquired the semaphore.\n"),
wxDateTime::Now().FormatTime().c_str(), m_i, (long)GetId());
Sleep(1000);
wxPrintf(wxT("%s: Thread #%d (%ld) releasing the semaphore.\n"),
wxDateTime::Now().FormatTime().c_str(), m_i, (long)GetId());
m_sem->Post();
return 0;
}
private:
wxSemaphore *m_sem;
int m_i;
};
WX_DEFINE_ARRAY_PTR(wxThread *, ArrayThreads);
static void TestSemaphore()
{
wxPuts(wxT("*** Testing wxSemaphore class. ***"));
static const int SEM_LIMIT = 3;
wxSemaphore sem(SEM_LIMIT, SEM_LIMIT);
ArrayThreads threads;
for ( int i = 0; i < 3*SEM_LIMIT; i++ )
{
threads.Add(new MySemaphoreThread(i, &sem));
threads.Last()->Run();
}
for ( size_t n = 0; n < threads.GetCount(); n++ )
{
threads[n]->Wait();
delete threads[n];
}
}
#endif // TEST_THREADS
// ----------------------------------------------------------------------------
// entry point
// ----------------------------------------------------------------------------
@@ -4150,24 +3752,6 @@ int main(int argc, char **argv)
TestTextInputStream();
#endif // TEST_TEXTSTREAM
#ifdef TEST_THREADS
int nCPUs = wxThread::GetCPUCount();
wxPrintf(wxT("This system has %d CPUs\n"), nCPUs);
if ( nCPUs != -1 )
wxThread::SetConcurrency(nCPUs);
TestJoinableThreads();
#if TEST_ALL
TestJoinableThreads();
TestDetachedThreads();
TestThreadSuspend();
TestThreadDelete();
TestThreadConditions();
TestSemaphore();
#endif
#endif // TEST_THREADS
#ifdef TEST_TIMER
TestStopWatch();
TestTimer();