]> git.saurik.com Git - wxWidgets.git/commitdiff
move code testing wxThread classes from the console sample to a new CppUnit test
authorFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Mon, 10 May 2010 21:48:24 +0000 (21:48 +0000)
committerFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Mon, 10 May 2010 21:48:24 +0000 (21:48 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64283 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

12 files changed:
samples/console/console.cpp
tests/Makefile.in
tests/makefile.bcc
tests/makefile.gcc
tests/makefile.vc
tests/makefile.wat
tests/test.bkl
tests/test_test.dsp
tests/test_vc7_test.vcproj
tests/test_vc8_test.vcproj
tests/test_vc9_test.vcproj
tests/thread/misc.cpp [new file with mode: 0644]

index d043138193077edef90c506f2d6d0194b98b465d..0052fd7b68064d74fd381ceb25eee64b13116fa0 100644 (file)
     #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();
index 4af8fdf6e807cb9790022e2a1f617cc5cdb1cdbe..df5ab92c41e6fd53acc732c853689db510ad5def 100644 (file)
@@ -113,6 +113,7 @@ TEST_OBJECTS =  \
        test_zlibstream.o \
        test_textfiletest.o \
        test_atomic.o \
+       test_misc.o \
        test_queue.o \
        test_tls.o \
        test_uris.o \
@@ -532,6 +533,9 @@ test_textfiletest.o: $(srcdir)/textfile/textfiletest.cpp $(TEST_ODEP)
 test_atomic.o: $(srcdir)/thread/atomic.cpp $(TEST_ODEP)
        $(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/thread/atomic.cpp
 
+test_misc.o: $(srcdir)/thread/misc.cpp $(TEST_ODEP)
+       $(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/thread/misc.cpp
+
 test_queue.o: $(srcdir)/thread/queue.cpp $(TEST_ODEP)
        $(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/thread/queue.cpp
 
index 40ba936ab313d9c0f6918c4d1428c49f08e0ae54..bbad494156c86c6a0097bdf052d3497c990414a1 100644 (file)
@@ -97,6 +97,7 @@ TEST_OBJECTS =  \
        $(OBJS)\test_zlibstream.obj \\r
        $(OBJS)\test_textfiletest.obj \\r
        $(OBJS)\test_atomic.obj \\r
+       $(OBJS)\test_misc.obj \\r
        $(OBJS)\test_queue.obj \\r
        $(OBJS)\test_tls.obj \\r
        $(OBJS)\test_uris.obj \\r
@@ -574,6 +575,9 @@ $(OBJS)\test_textfiletest.obj: .\textfile\textfiletest.cpp
 $(OBJS)\test_atomic.obj: .\thread\atomic.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\thread\atomic.cpp\r
 \r
+$(OBJS)\test_misc.obj: .\thread\misc.cpp\r
+       $(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\thread\misc.cpp\r
+\r
 $(OBJS)\test_queue.obj: .\thread\queue.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\thread\queue.cpp\r
 \r
index 972889d68b4bdd44a8c20b8acfb71c616848c356..b250c6377bba5b9c27af30066ccbe20b988d2017 100644 (file)
@@ -89,6 +89,7 @@ TEST_OBJECTS =  \
        $(OBJS)\test_zlibstream.o \\r
        $(OBJS)\test_textfiletest.o \\r
        $(OBJS)\test_atomic.o \\r
+       $(OBJS)\test_misc.o \\r
        $(OBJS)\test_queue.o \\r
        $(OBJS)\test_tls.o \\r
        $(OBJS)\test_uris.o \\r
@@ -555,6 +556,9 @@ $(OBJS)\test_textfiletest.o: ./textfile/textfiletest.cpp
 $(OBJS)\test_atomic.o: ./thread/atomic.cpp\r
        $(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<\r
 \r
+$(OBJS)\test_misc.o: ./thread/misc.cpp\r
+       $(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<\r
+\r
 $(OBJS)\test_queue.o: ./thread/queue.cpp\r
        $(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<\r
 \r
index 1f005bf184fdfeb023c293eeac57f47817653961..237822026f04155f665c46cdd4b015aa216e23ff 100644 (file)
@@ -91,6 +91,7 @@ TEST_OBJECTS =  \
        $(OBJS)\test_zlibstream.obj \\r
        $(OBJS)\test_textfiletest.obj \\r
        $(OBJS)\test_atomic.obj \\r
+       $(OBJS)\test_misc.obj \\r
        $(OBJS)\test_queue.obj \\r
        $(OBJS)\test_tls.obj \\r
        $(OBJS)\test_uris.obj \\r
@@ -700,6 +701,9 @@ $(OBJS)\test_textfiletest.obj: .\textfile\textfiletest.cpp
 $(OBJS)\test_atomic.obj: .\thread\atomic.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\thread\atomic.cpp\r
 \r
+$(OBJS)\test_misc.obj: .\thread\misc.cpp\r
+       $(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\thread\misc.cpp\r
+\r
 $(OBJS)\test_queue.obj: .\thread\queue.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\thread\queue.cpp\r
 \r
index d7db26faec6adacf8faf01af70379fac19a6a433..7fca6b4ccb04f75cc5932aad767f6508f5352a90 100644 (file)
@@ -327,6 +327,7 @@ TEST_OBJECTS =  &
        $(OBJS)\test_zlibstream.obj &\r
        $(OBJS)\test_textfiletest.obj &\r
        $(OBJS)\test_atomic.obj &\r
+       $(OBJS)\test_misc.obj &\r
        $(OBJS)\test_queue.obj &\r
        $(OBJS)\test_tls.obj &\r
        $(OBJS)\test_uris.obj &\r
@@ -612,6 +613,9 @@ $(OBJS)\test_textfiletest.obj :  .AUTODEPEND .\textfile\textfiletest.cpp
 $(OBJS)\test_atomic.obj :  .AUTODEPEND .\thread\atomic.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<\r
 \r
+$(OBJS)\test_misc.obj :  .AUTODEPEND .\thread\misc.cpp\r
+       $(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<\r
+\r
 $(OBJS)\test_queue.obj :  .AUTODEPEND .\thread\queue.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<\r
 \r
index eac3d28888e1d07fda0db3aa484531bd2c75a879..629d6049e81dbeb3acd53ada26afc9d16dcce989 100644 (file)
@@ -88,6 +88,7 @@
             streams/zlibstream.cpp
             textfile/textfiletest.cpp
             thread/atomic.cpp
+            thread/misc.cpp
             thread/queue.cpp
             thread/tls.cpp
             uris/uris.cpp
index 9f353988e3b2f75b1e4b74aa3f04089c5a737934..271690fa8b871d16ab7d4c3d9f415832eb23d0f4 100644 (file)
@@ -389,6 +389,10 @@ SOURCE=.\streams\memstream.cpp
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\thread\misc.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\misc\misctests.cpp\r
 # End Source File\r
 # Begin Source File\r
index 12dc231b82ee5647ac5842d5b7d5b580ab3f7769..874d981a3517ec9a5b98efba90012ee3505e4537 100644 (file)
                        <File\r
                                RelativePath=".\streams\memstream.cpp">\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\thread\misc.cpp">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\misc\misctests.cpp">\r
                        </File>\r
index da3dad6eed917bd1d5fa3e921bfa93f0361a65aa..7254ddcb877fce2c043458ff00b1f30f29f98c8c 100644 (file)
                                RelativePath=".\streams\memstream.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\thread\misc.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\misc\misctests.cpp"\r
                                >\r
index 80f59fbfb82e5c0c15276f803ebbab3557e0d0ea..071b74f23ae6c73b9ffe9ff3064568cde5840637 100644 (file)
@@ -1,16 +1,10 @@
 <?xml version="1.0" encoding="Windows-1252"?>\r
-<!--\r
-\r
-  This project was generated by\r
-  Bakefile 0.2.8 (http://www.bakefile.org)\r
-  Do not modify, all changes will be overwritten!\r
-\r
--->\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
-       Version="9.00"\r
+       Version="9,00"\r
        Name="test"\r
        ProjectGUID="{2F45723C-ED6B-5F60-8BFF-6B3609464A7B}"\r
+       TargetFrameworkVersion="0"\r
        >\r
        <Platforms>\r
                <Platform\r
@@ -18,7 +12,6 @@
                />\r
        </Platforms>\r
        <ToolFiles>\r
-               \r
        </ToolFiles>\r
        <Configurations>\r
                <Configuration\r
@@ -51,7 +44,7 @@
                                Name="VCCLCompilerTool"\r
                                AdditionalOptions="/MP"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories=".\..\lib\vc_lib\mswud;.\..\include;."\r
+                               AdditionalIncludeDirectories=".\..\lib\vc_lib\mswud;.\..\include;.;F:\cppunit\include"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;__WXMSW__;_UNICODE;_CONSOLE;wxUSE_GUI=0"\r
                                ExceptionHandling="1"\r
                                BasicRuntimeChecks="3"\r
@@ -86,7 +79,7 @@
                                OutputFile="vc_mswud\test.exe"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories=".\..\lib\vc_lib"\r
+                               AdditionalLibraryDirectories=".\..\lib\vc_lib;F:\cppunit\lib"\r
                                GenerateManifest="true"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="vc_mswud\test.pdb"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswud\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswud\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="vc_mswu\test.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswu\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswu\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswunivud\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswunivud\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="vc_mswunivu\test.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswunivu\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswunivu\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswuddll\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswuddll\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="vc_mswudll\test.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswudll\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswudll\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswunivuddll\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswunivuddll\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="vc_mswunivudll\test.pdb"\r
                                SubSystem="1"\r
-                               TargetMachine="1"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                        <Tool\r
                                Name="VCBscMakeTool"\r
-                               OutputFile="vc_mswunivudll\test_vc9_test.bsc"\r
                                SuppressStartupBanner="true"\r
+                               OutputFile="vc_mswunivudll\test_vc9_test.bsc"\r
                        />\r
                        <Tool\r
                                Name="VCFxCopTool"\r
                </Configuration>\r
        </Configurations>\r
        <References>\r
-               \r
        </References>\r
        <Files>\r
                <Filter\r
                                RelativePath=".\streams\memstream.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\thread\misc.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\misc\misctests.cpp"\r
                                >\r
                </Filter>\r
        </Files>\r
        <Globals>\r
-               \r
        </Globals>\r
 </VisualStudioProject>\r
-\r
diff --git a/tests/thread/misc.cpp b/tests/thread/misc.cpp
new file mode 100644 (file)
index 0000000..d2eb6aa
--- /dev/null
@@ -0,0 +1,407 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        tests/thread/misc.cpp
+// Purpose:     Miscellaneous wxThread test cases
+// Author:      Francesco Montorsi (extracted from console sample)
+// Created:     2010-05-10
+// RCS-ID:      $Id$
+// Copyright:   (c) 2010 wxWidgets team
+///////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "testprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#endif // WX_PRECOMP
+
+#include "wx/thread.h"
+#include "wx/tls.h"
+
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+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 :-)
+        wxMilliSleep(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();
+}
+
+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());
+        gs_cond.Post();
+
+        //wxPrintf(wxT("Thread %lu starts to wait...\n"), GetId());
+
+        m_mutex->Lock();
+        m_condition->Wait();
+        m_mutex->Unlock();
+
+        //wxPrintf(wxT("Thread %lu finished to wait, exiting.\n"), GetId());
+
+        return 0;
+    }
+
+private:
+    wxMutex *m_mutex;
+    wxCondition *m_condition;
+};
+
+// 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);
+
+// ----------------------------------------------------------------------------
+// test class
+// ----------------------------------------------------------------------------
+
+class MiscThreadTestCase : public CppUnit::TestCase
+{
+public:
+    MiscThreadTestCase();
+
+private:
+    CPPUNIT_TEST_SUITE( MiscThreadTestCase );
+        CPPUNIT_TEST( TestJoinable );
+        CPPUNIT_TEST( TestDetached );
+        CPPUNIT_TEST( TestThreadSuspend );
+        CPPUNIT_TEST( TestThreadDelete );
+        CPPUNIT_TEST( TestThreadConditions );
+        CPPUNIT_TEST( TestSemaphore );
+    CPPUNIT_TEST_SUITE_END();
+
+    void TestJoinable();
+    void TestDetached();
+    void TestSemaphore();
+
+    void TestThreadSuspend();
+    void TestThreadDelete();
+    void TestThreadConditions();
+
+    DECLARE_NO_COPY_CLASS(MiscThreadTestCase)
+};
+
+// register in the unnamed registry so that these tests are run by default
+CPPUNIT_TEST_SUITE_REGISTRATION( MiscThreadTestCase );
+
+// also include in it's own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MiscThreadTestCase, "MiscThreadTestCase" );
+
+MiscThreadTestCase::MiscThreadTestCase()
+{
+    int nCPUs = wxThread::GetCPUCount();
+    if ( nCPUs != -1 )
+        wxThread::SetConcurrency(nCPUs);
+}
+
+void MiscThreadTestCase::TestJoinable()
+{
+    // calc 10! in the background
+    MyJoinableThread thread(10);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread.Run() );
+    CPPUNIT_ASSERT_EQUAL( 362880, (unsigned long)thread.Wait() );
+}
+void MiscThreadTestCase::TestDetached()
+{
+    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++ )
+    {
+        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, threads[n]->Run() );
+    }
+
+    // wait until all threads terminate
+    CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );
+}
+
+void MiscThreadTestCase::TestSemaphore()
+{
+    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));
+        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, threads.Last()->Run() );
+    }
+
+    for ( size_t n = 0; n < threads.GetCount(); n++ )
+    {
+        CPPUNIT_ASSERT_EQUAL( 0, (long)threads[n]->Wait() );
+        delete threads[n];
+    }
+}
+
+void MiscThreadTestCase::TestThreadSuspend()
+{
+    MyDetachedThread *thread = new MyDetachedThread(15, 'X');
+
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, 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();
+
+        if ( n > 0 )
+        {
+            // don't sleep but resume immediately the first time
+            wxThread::Sleep(300);
+        }
+
+        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread->Resume() );
+    }
+
+    // wait until the thread terminates
+    CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );
+}
+
+void MiscThreadTestCase::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!
+
+    MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_MISC_ERROR, thread0->Delete() );    
+        // delete a thread which didn't start to run yet.
+
+    MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread1->Run() );
+    wxThread::Sleep(300);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread1->Delete() );      
+        // delete a running thread
+
+    MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread2->Run() );
+    wxThread::Sleep(300);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread2->Pause() );
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread2->Delete() );      
+        // delete a sleeping thread
+
+    MyJoinableThread thread3(20);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread3.Run() );
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread3.Delete() );       
+        // delete a joinable thread
+
+    MyJoinableThread thread4(2);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread4.Run() );
+    wxThread::Sleep(300);
+    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread4.Delete() );       
+        // delete a joinable thread which already terminated
+}
+
+void MiscThreadTestCase::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++ )
+    {
+        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, threads[n]->Run() );
+    }
+
+    // wait until all threads run
+    // NOTE: main thread is waiting for the other threads to start
+    size_t nRunning = 0;
+    while ( nRunning < WXSIZEOF(threads) )
+    {
+        CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );
+
+        nRunning++;
+
+        // note that main thread is already running
+    }
+
+    wxThread::Sleep(500);
+
+#if 1
+    // now wake one of them up
+    CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, condition.Signal() );
+#endif
+
+    wxThread::Sleep(200);
+
+    // wake all the (remaining) threads up, so that they can exit
+    CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, condition.Broadcast() );
+
+    // give them time to terminate (dirty!)
+    wxThread::Sleep(500);
+}