]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/threadpsx.cpp
fixed wxUSE_TABDIALOG/TAB_DIALOG confusion and other fixes to prevent wxTabCtrl from...
[wxWidgets.git] / src / unix / threadpsx.cpp
index 3fdf392751585f76c825444e1387907168a1c8c4..d1a8b82f60e5bba27adf8fdc5be592782975541c 100644 (file)
@@ -10,7 +10,7 @@
 //                  Vadim Zeitlin (1999-2002)
 //                  Robert Roebling (1999)
 //                  K. S. Sreeram (2002)
-// Licence:     wxWidgets licence
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 // headers
 // ----------------------------------------------------------------------------
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "thread.h"
-#endif
-
 // for compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #include "wx/intl.h"
 #include "wx/dynarray.h"
 #include "wx/timer.h"
+#include "wx/stopwatch.h"
 
 #include <stdio.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <errno.h>
 #include <time.h>
-#if HAVE_SCHED_H
+#ifdef HAVE_SCHED_H
     #include <sched.h>
 #endif
 
@@ -99,7 +96,7 @@ static void DeleteThread(wxThread *This);
 // ----------------------------------------------------------------------------
 
 // an (non owning) array of pointers to threads
-WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
+WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
 
 // an entry for a thread we can wait for
 
@@ -173,7 +170,8 @@ private:
     friend class wxConditionInternal;
 };
 
-#ifdef HAVE_PTHREAD_MUTEXATTR_T
+#if defined(HAVE_PTHREAD_MUTEXATTR_T) && \
+        wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL)
 // on some systems pthread_mutexattr_settype() is not in the headers (but it is
 // in the library, otherwise we wouldn't compile this code at all)
 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
@@ -590,10 +588,10 @@ wxSemaError wxSemaphoreInternal::Post()
 extern "C"
 {
 
-#if HAVE_THREAD_CLEANUP_FUNCTIONS
+#ifdef wxHAVE_PTHREAD_CLEANUP
     // thread exit function
     void wxPthreadCleanup(void *ptr);
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+#endif // wxHAVE_PTHREAD_CLEANUP
 
 void *wxPthreadStart(void *ptr);
 
@@ -670,10 +668,10 @@ public:
         m_isDetached = TRUE;
     }
 
-#if HAVE_THREAD_CLEANUP_FUNCTIONS
+#ifdef wxHAVE_PTHREAD_CLEANUP
     // this is used by wxPthreadCleanup() only
     static void Cleanup(wxThread *thread);
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+#endif // wxHAVE_PTHREAD_CLEANUP
 
 private:
     pthread_t     m_threadId;   // id of the thread
@@ -734,11 +732,11 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
     // block!
     bool dontRunAtAll;
 
-#if HAVE_THREAD_CLEANUP_FUNCTIONS
+#ifdef wxHAVE_PTHREAD_CLEANUP
     // install the cleanup handler which will be called if the thread is
     // cancelled
     pthread_cleanup_push(wxPthreadCleanup, thread);
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+#endif // wxHAVE_PTHREAD_CLEANUP
 
     // wait for the semaphore to be posted from Run()
     pthread->m_semRun.Wait();
@@ -763,7 +761,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
 
         wxLogTrace(TRACE_THREADS,
                    _T("Thread %ld Entry() returned %lu."),
-                   THR_ID(pthread), (unsigned long)pthread->m_exitcode);
+                   THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode));
 
         {
             wxCriticalSectionLocker lock(thread->m_critsect);
@@ -775,13 +773,22 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
         }
     }
 
-    // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop
-    //     contains the matching '}' for the '{' in push, so they must be used
-    //     in the same block!
-#if HAVE_THREAD_CLEANUP_FUNCTIONS
+    // NB: pthread_cleanup_push/pop() are macros and pop contains the matching
+    //     '}' for the '{' in push, so they must be used in the same block!
+#ifdef wxHAVE_PTHREAD_CLEANUP
+    #ifdef __DECCXX
+        // under Tru64 we get a warning from macro expansion
+        #pragma message save
+        #pragma message disable(declbutnotref)
+    #endif
+
     // remove the cleanup handler without executing it
     pthread_cleanup_pop(FALSE);
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+
+    #ifdef __DECCXX
+        #pragma message restore
+    #endif
+#endif // wxHAVE_PTHREAD_CLEANUP
 
     if ( dontRunAtAll )
     {
@@ -801,7 +808,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
     }
 }
 
-#if HAVE_THREAD_CLEANUP_FUNCTIONS
+#ifdef wxHAVE_PTHREAD_CLEANUP
 
 // this handler is called when the thread is cancelled
 extern "C" void wxPthreadCleanup(void *ptr)
@@ -811,6 +818,7 @@ extern "C" void wxPthreadCleanup(void *ptr)
 
 void wxThreadInternal::Cleanup(wxThread *thread)
 {
+    if (pthread_getspecific(gs_keySelf) == 0) return;
     {
         wxCriticalSectionLocker lock(thread->m_critsect);
         if ( thread->m_internal->GetState() == STATE_EXITED )
@@ -824,7 +832,7 @@ void wxThreadInternal::Cleanup(wxThread *thread)
     thread->Exit(EXITCODE_CANCELLED);
 }
 
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+#endif // wxHAVE_PTHREAD_CLEANUP
 
 // ----------------------------------------------------------------------------
 // wxThreadInternal
@@ -969,7 +977,7 @@ void wxThread::Yield()
 
 void wxThread::Sleep(unsigned long milliseconds)
 {
-    wxUsleep(milliseconds);
+    wxMilliSleep(milliseconds);
 }
 
 int wxThread::GetCPUCount()
@@ -1061,7 +1069,13 @@ wxThread::wxThread(wxThreadKind kind)
     m_isDetached = kind == wxTHREAD_DETACHED;
 }
 
-wxThreadError wxThread::Create(unsigned int WXUNUSED(stackSize))
+#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+    #define WXUNUSED_STACKSIZE(identifier)  identifier
+#else
+    #define WXUNUSED_STACKSIZE(identifier)  WXUNUSED(identifier)
+#endif
+
+wxThreadError wxThread::Create(unsigned int WXUNUSED_STACKSIZE(stackSize))
 {
     if ( m_internal->GetState() != STATE_NEW )
     {
@@ -1073,6 +1087,11 @@ wxThreadError wxThread::Create(unsigned int WXUNUSED(stackSize))
     pthread_attr_t attr;
     pthread_attr_init(&attr);
 
+#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+    if (stackSize)
+      pthread_attr_setstacksize(&attr, stackSize);
+#endif
+
 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
     int policy;
     if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 )
@@ -1207,42 +1226,21 @@ void wxThread::SetPriority(unsigned int prio)
         case STATE_PAUSED:
 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
 #if defined(__LINUX__)
-// On Linux, pthread_setschedparam with SCHED_OTHER does not allow
-// a priority other than 0.  Instead, we use the BSD setpriority
-// which alllows us to set a 'nice' value between 20 to -20.  Only
-// super user can set a value less than zero (more negative yields
-// higher priority).  setpriority set the static priority of a process,
-// but this is OK since Linux is configured as a thread per process.
-            {
-                float   fPrio;
-                float  pSpan;
-                int            iPrio;
-
-                // Map Wx priorites (WXTHREAD_MIN_PRIORITY -
-                // WXTHREAD_MAX_PRIORITY) into BSD priorities (20 - -20).
-                // Do calculation of values instead of hard coding them
-                // to make maintenance easier.
-
-                pSpan = ((float)(WXTHREAD_MAX_PRIORITY - WXTHREAD_MIN_PRIORITY)) / 2.0;
-
-                // prio starts as ...................  // value =>  (0) >=  p  <=  (n)
-
-                fPrio = ((float)prio) -  pSpan;        // value =>  (-n) >=  p  <=  (+n)
-
-                fPrio = 0.0 - fPrio;                   // value =>  (+n) <=  p  >=  (-n)
-
-                fPrio = fPrio * (20. / pSpan) + .5;    // value =>  (20) <=  p  >=  (-20)
-
-                iPrio = (int)fPrio;
-
-                // Clamp prio from 20 - -20;
-                iPrio = (iPrio > 20)  ?  20 : iPrio;
-                iPrio = (iPrio < -20) ? -20 : iPrio;
+            // On Linux, pthread_setschedparam with SCHED_OTHER does not allow
+            // a priority other than 0.  Instead, we use the BSD setpriority
+            // which alllows us to set a 'nice' value between 20 to -20.  Only
+            // super user can set a value less than zero (more negative yields
+            // higher priority).  setpriority set the static priority of a
+            // process, but this is OK since Linux is configured as a thread
+            // per process.
+            //
+            // FIXME this is not true for 2.6!!
 
-                if (setpriority(PRIO_PROCESS, 0, iPrio) == -1)
-                {
-                    wxLogError(_("Failed to set thread priority %d."), prio);
-                }
+            // map wx priorites WXTHREAD_MIN_PRIORITY..WXTHREAD_MAX_PRIORITY
+            // to Unix priorities 20..-20
+            if ( setpriority(PRIO_PROCESS, 0, -(2*prio)/5 + 20) == -1 )
+            {
+                wxLogError(_("Failed to set thread priority %d."), prio);
             }
 #else // __LINUX__
             {
@@ -1423,25 +1421,26 @@ wxThreadError wxThread::Kill()
         default:
 #ifdef HAVE_PTHREAD_CANCEL
             if ( pthread_cancel(m_internal->GetId()) != 0 )
-#endif
+#endif // HAVE_PTHREAD_CANCEL
             {
                 wxLogError(_("Failed to terminate a thread."));
 
                 return wxTHREAD_MISC_ERROR;
             }
 
+#ifdef HAVE_PTHREAD_CANCEL
             if ( m_isDetached )
             {
                 // if we use cleanup function, this will be done from
                 // wxPthreadCleanup()
-#if !HAVE_THREAD_CLEANUP_FUNCTIONS
+#ifndef wxHAVE_PTHREAD_CLEANUP
                 ScheduleThreadForDeletion();
 
                 // don't call OnExit() here, it can only be called in the
                 // threads context and we're in the context of another thread
 
                 DeleteThread(this);
-#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+#endif // wxHAVE_PTHREAD_CLEANUP
             }
             else
             {
@@ -1449,6 +1448,7 @@ wxThreadError wxThread::Kill()
             }
 
             return wxTHREAD_NO_ERROR;
+#endif // HAVE_PTHREAD_CANCEL
     }
 }
 
@@ -1482,6 +1482,13 @@ void wxThread::Exit(ExitCode status)
         //       we make it a global object, but this would mean that we can
         //       only call one thread function at a time :-(
         DeleteThread(this);
+        pthread_setspecific(gs_keySelf, 0);
+    }
+    else
+    {
+        m_critsect.Enter();
+        m_internal->SetState(STATE_EXITED);
+        m_critsect.Leave();
     }
 
     // terminate the thread (pthread_exit() never returns)
@@ -1527,7 +1534,8 @@ wxThread::~wxThread()
     if ( m_internal->GetState() != STATE_EXITED &&
          m_internal->GetState() != STATE_NEW )
     {
-        wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId());
+        wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."),
+                   (long)GetId());
     }
 
     m_critsect.Leave();