]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/console/console.cpp
joinable and detached POSIX threads (not fully tested yet)
[wxWidgets.git] / samples / console / console.cpp
index 8b8fbcf9e1a9b0bccb21524844d0793aa43946bc..f72458ddd57d23a9a89efa2703131f36700d399e 100644 (file)
 // ----------------------------------------------------------------------------
 
 // what to test?
-#define TEST_ARRAYS
-#undef TEST_THREADS
+
+//#define TEST_ARRAYS
+//#define TEST_LOG
+//#define TEST_STRINGS
+#define TEST_THREADS
+//#define TEST_TIME
+//#define TEST_LONGLONG
 
 // ============================================================================
 // implementation
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// long long
+// ----------------------------------------------------------------------------
+
+#ifdef TEST_LONGLONG
+
+#include <wx/longlong.h>
+#include <wx/timer.h>
+
+static void TestSpeed()
+{
+    static const long max = 100000000;
+    long n;
+
+    {
+        wxStopWatch sw;
+
+        long l = 0;
+        for ( n = 0; n < max; n++ )
+        {
+            l += n;
+        }
+
+        printf("Summing longs took %ld milliseconds.\n", sw.Time());
+    }
+
+    {
+        wxStopWatch sw;
+
+        __int64 l = 0;
+        for ( n = 0; n < max; n++ )
+        {
+            l += n;
+        }
+
+        printf("Summing __int64s took %ld milliseconds.\n", sw.Time());
+    }
+
+    {
+        wxStopWatch sw;
+
+        wxLongLong l;
+        for ( n = 0; n < max; n++ )
+        {
+            l += n;
+        }
+
+        printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
+    }
+}
+
+static void TestDivision()
+{
+    wxLongLong ll = 0x38417388; // some number < LONG_MAX
+
+    wxASSERT( (ll / 1000l)*1000l == ll );
+}
+
+#endif // TEST_LONGLONG
+
+// ----------------------------------------------------------------------------
+// date time
+// ----------------------------------------------------------------------------
+
+#ifdef TEST_TIME
+
+#include <wx/datetime.h>
+
+#endif // TEST_TIME
+
 // ----------------------------------------------------------------------------
 // threads
 // ----------------------------------------------------------------------------
 
 static size_t gs_counter = (size_t)-1;
 static wxCriticalSection gs_critsect;
+static wxCondition gs_cond;
 
-class MyThread : public wxThread
+class MyJoinableThread : public wxThread
 {
 public:
-    MyThread(char ch);
+    MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
+        { m_n = n; Create(); }
 
     // thread execution starts here
-    virtual void *Entry();
-
-    // and stops here
-    virtual void OnExit();
+    virtual ExitCode Entry();
 
-public:
-    char m_ch;
+private:
+    size_t m_n;
 };
 
-MyThread::MyThread(char ch)
+wxThread::ExitCode MyJoinableThread::Entry()
 {
-    m_ch = ch;
+    unsigned long res = 1;
+    for ( size_t n = 1; n < m_n; n++ )
+    {
+        res *= n;
 
-    Create();
+        // it's a loooong calculation :-)
+        Sleep(100);
+    }
+
+    return (ExitCode)res;
 }
 
-void *MyThread::Entry()
+class MyDetachedThread : public wxThread
+{
+public:
+    MyDetachedThread(size_t n, char ch) { m_n = n; m_ch = ch; Create(); }
+
+    // thread execution starts here
+    virtual ExitCode Entry();
+
+    // and stops here
+    virtual void OnExit();
+
+private:
+    size_t m_n; // number of characters to write
+    char m_ch;  // character to write
+};
+
+wxThread::ExitCode MyDetachedThread::Entry()
 {
     {
         wxCriticalSectionLocker lock(gs_critsect);
@@ -78,7 +175,7 @@ void *MyThread::Entry()
             gs_counter++;
     }
 
-    for ( size_t n = 0; n < 10; n++ )
+    for ( size_t n = 0; n < m_n; n++ )
     {
         if ( TestDestroy() )
             break;
@@ -89,13 +186,89 @@ void *MyThread::Entry()
         wxThread::Sleep(100);
     }
 
-    return NULL;
+    return 0;
 }
 
-void MyThread::OnExit()
+void MyDetachedThread::OnExit()
 {
+    wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
+
     wxCriticalSectionLocker lock(gs_critsect);
-    gs_counter--;
+    if ( !--gs_counter )
+        gs_cond.Signal();
+}
+
+void TestDetachedThreads()
+{
+    puts("*** 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();
+
+    puts("");
+}
+
+void TestJoinableThreads()
+{
+    puts("*** Testing a joinable thread (a loooong calculation...) ***");
+
+    // calc 10! in the background
+    MyJoinableThread thread(10);
+    thread.Run();
+
+    printf("\nThread terminated with exit code %lu.\n",
+           (unsigned long)thread.Wait());
+}
+
+void TestThreadSuspend()
+{
+    MyDetachedThread *thread = new MyDetachedThread(30, '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();
+
+        puts("\nThread suspended");
+        if ( n > 0 )
+        {
+            // don't sleep but resume immediately the first time
+            wxThread::Sleep(300);
+        }
+        puts("Going to resume the thread");
+
+        thread->Resume();
+    }
+
+    // wait until the thread terminates
+    gs_cond.Wait();
+
+    puts("");
 }
 
 #endif // TEST_THREADS
@@ -119,6 +292,64 @@ void PrintArray(const char* name, const wxArrayString& array)
 
 #endif // TEST_ARRAYS
 
+// ----------------------------------------------------------------------------
+// strings
+// ----------------------------------------------------------------------------
+
+#ifdef TEST_STRINGS
+
+#include "wx/timer.h"
+
+void TestString()
+{
+    wxStopWatch sw;
+
+    wxString a, b, c;
+
+    a.reserve (128);
+    b.reserve (128);
+    c.reserve (128);
+
+    for (int i = 0; i < 1000000; ++i)
+    {
+        a = "Hello";
+        b = " world";
+        c = "! How'ya doin'?";
+        a += b;
+        a += c;
+        c = "Hello world! What's up?";
+        if (c != a)
+            c = "Doh!";
+    }
+
+    printf ("TestString elapsed time: %ld\n", sw.Time());
+}
+
+void TestPChar()
+{
+    wxStopWatch sw;
+
+    char a [128];
+    char b [128];
+    char c [128];
+
+    for (int i = 0; i < 1000000; ++i)
+    {
+        strcpy (a, "Hello");
+        strcpy (b, " world");
+        strcpy (c, "! How'ya doin'?");
+        strcat (a, b);
+        strcat (a, c);
+        strcpy (c, "Hello world! What's up?");
+        if (strcmp (c, a) == 0)
+            strcpy (c, "Doh!");
+    }
+
+    printf ("TestPChar elapsed time: %ld\n", sw.Time());
+}
+
+#endif // TEST_STRINGS
+
 // ----------------------------------------------------------------------------
 // entry point
 // ----------------------------------------------------------------------------
@@ -130,6 +361,11 @@ int main(int argc, char **argv)
         fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
     }
 
+#ifdef TEST_STRINGS
+    TestPChar();
+    TestString();
+#endif // TEST_STRINGS
+
 #ifdef TEST_ARRAYS
     wxArrayString a1;
     a1.Add("tiger");
@@ -162,32 +398,52 @@ int main(int argc, char **argv)
     PrintArray("a3", a3);
 #endif // TEST_ARRAYS
 
-#ifdef TEST_THREADS
-    static const size_t nThreads = 3;
-    MyThread *threads[nThreads];
-    size_t n;
-    for ( n = 0; n < nThreads; n++ )
+#ifdef TEST_LOG
+    wxString s;
+    for ( size_t n = 0; n < 8000; n++ )
     {
-        threads[n] = new MyThread('+' + n);
-        threads[n]->Run();
+        s << (char)('A' + (n % 26));
     }
 
-    // wait until all threads terminate
-    for ( ;; )
-    {
-        wxCriticalSectionLocker lock(gs_critsect);
-        if ( !gs_counter )
-            break;
-    }
+    wxString msg;
+    msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
 
-    puts("\nThat's all, folks!");
+    // this one shouldn't be truncated
+    printf(msg);
 
-    for ( n = 0; n < nThreads; n++ )
+    // but this one will because log functions use fixed size buffer
+    // (note that it doesn't need '\n' at the end neither - will be added
+    //  by wxLog anyhow)
+    wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
+#endif // TEST_LOG
+
+#ifdef TEST_THREADS
+    if ( argc > 1 && argv[1][0] == 't' )
+        wxLog::AddTraceMask("thread");
+
+    TestThreadSuspend();
+    if ( 0 )
     {
-        threads[n]->Delete();
+    TestDetachedThreads();
+    TestJoinableThreads();
     }
 #endif // TEST_THREADS
 
+#ifdef TEST_LONGLONG
+    if ( 0 )
+        TestSpeed();
+    if ( 1 )
+        TestDivision();
+#endif // TEST_LONGLONG
+
+#ifdef TEST_TIME
+    wxDateTime time = wxDateTime::Now();
+    printf("Current time: '%s', current year %u is %sa leap one",
+           time.Format().c_str(),
+           time.GetYear(),
+           wxDateTime::IsLeapYear(time.GetYear()) ? "" : "not");
+#endif // TEST_TIME
+
     wxUninitialize();
 
     return 0;