X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ee4f8c2af9c6c5458e488db10aef7d00a89ace25..db1b49617679e97304ddc36491bfcdc14381d904:/src/gtk/threadpsx.cpp?ds=sidebyside diff --git a/src/gtk/threadpsx.cpp b/src/gtk/threadpsx.cpp index ce5396c6d7..4219e404be 100644 --- a/src/gtk/threadpsx.cpp +++ b/src/gtk/threadpsx.cpp @@ -14,12 +14,17 @@ #include #include -#include #include +#include +#include "wx/thread.h" +#include "wx/module.h" +#include "wx/utils.h" enum thread_state { STATE_IDLE = 0, STATE_RUNNING, + STATE_PAUSING, + STATE_PAUSED, STATE_CANCELED, STATE_EXITED }; @@ -28,10 +33,11 @@ enum thread_state { // Static variables ///////////////////////////////////////////////////////////////////////////// -#include "thread.h" - static pthread_t p_mainid; -wxMutex wxMainMutex; // controls access to all GUI functions +static wxMutex p_list_mutex; +static wxList p_threads_list; + +wxMutex *wxMainMutex; // controls access to all GUI functions ///////////////////////////////////////////////////////////////////////////// // GUI thread manager @@ -51,13 +57,15 @@ wxMutex::wxMutex() { p_internal = new wxMutexInternal; pthread_mutex_init(&(p_internal->p_mutex), NULL); - m_locked = false; + m_locked = 0; } wxMutex::~wxMutex() { - if (m_locked) - pthread_mutex_unlock(&(p_internal->p_mutex)); + if (m_locked > 0) + wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", + m_locked); + pthread_mutex_destroy(&(p_internal->p_mutex)); delete p_internal; } @@ -67,9 +75,8 @@ wxMutexError wxMutex::Lock() int err; err = pthread_mutex_lock(&(p_internal->p_mutex)); - switch (err) { - case EDEADLK: return MUTEX_DEAD_LOCK; - } + if (err == EDEADLK) + return MUTEX_DEAD_LOCK; m_locked++; return MUTEX_NO_ERROR; } @@ -90,7 +97,10 @@ wxMutexError wxMutex::TryLock() wxMutexError wxMutex::Unlock() { - if (m_locked > 0) m_locked--; + if (m_locked > 0) + m_locked--; + else + return MUTEX_UNLOCKED; pthread_mutex_unlock(&(p_internal->p_mutex)); return MUTEX_NO_ERROR; } @@ -152,14 +162,24 @@ public: pthread_t thread_id; int state; int prio; + int defer_destroy; + int id; }; void *wxThreadInternal::PthreadStart(void *ptr) { wxThread *thread = (wxThread *)ptr; + // Add the current thread to the list + p_list_mutex.Lock(); + thread->p_internal->id = p_threads_list.Number(); + p_threads_list.Append((wxObject *)thread); + p_list_mutex.Unlock(); + + // Call the main entry pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); void* status = thread->Entry(); + thread->Exit(status); return NULL; @@ -195,6 +215,7 @@ wxThreadError wxThread::Create() return THREAD_NO_RESOURCE; } pthread_attr_destroy(&a); + return THREAD_NO_ERROR; } @@ -232,6 +253,27 @@ wxThreadError wxThread::Destroy() if (res == 0) p_internal->state = STATE_CANCELED; } + + return THREAD_NO_ERROR; +} + +wxThreadError wxThread::Pause() +{ + if (p_internal->state != STATE_RUNNING) + return THREAD_NOT_RUNNING; + + if (!p_internal->defer_destroy) + return THREAD_MISC_ERROR; + + p_internal->state = STATE_PAUSING; + return THREAD_NO_ERROR; +} + +wxThreadError wxThread::Resume() +{ + if (p_internal->state == STATE_PAUSING || p_internal->state == STATE_PAUSED) + p_internal->state = STATE_RUNNING; + return THREAD_NO_ERROR; } @@ -246,10 +288,15 @@ void *wxThread::Join() wxYield(); if (do_unlock) - wxMainMutex.Unlock(); + wxMainMutex->Unlock(); pthread_join(p_internal->thread_id, &status); if (do_unlock) - wxMainMutex.Lock(); + wxMainMutex->Lock(); + + p_list_mutex.Lock(); + delete p_threads_list.Nth(p_internal->id); + p_list_mutex.Unlock(); + p_internal->state = STATE_IDLE; } return status; @@ -257,7 +304,16 @@ void *wxThread::Join() unsigned long wxThread::GetID() const { - return (unsigned long)p_internal->thread_id; + return p_internal->id; +} + +wxThread *wxThread::GetThreadFromID(unsigned long id) +{ + wxNode *node = p_threads_list.Nth(id); + + if (!node) + return NULL; + return (wxThread *)node->Data(); } void wxThread::Exit(void *status) @@ -271,14 +327,33 @@ void wxThread::Exit(void *status) void wxThread::TestDestroy() { + if (p_internal->state == STATE_PAUSING) { + p_internal->state = STATE_PAUSED; + while (p_internal->state == STATE_PAUSED) { + pthread_testcancel(); + usleep(1); + } + } pthread_testcancel(); } -bool wxThread::IsMain() const +bool wxThread::IsMain() { return (bool)pthread_equal(pthread_self(), p_mainid); } +bool wxThread::IsRunning() const +{ + return (p_internal->state == STATE_RUNNING); +} + +bool wxThread::IsAlive() const +{ + return (p_internal->state == STATE_RUNNING) || + (p_internal->state == STATE_PAUSING) || + (p_internal->state == STATE_PAUSED); +} + wxThread::wxThread() { p_internal = new wxThreadInternal(); @@ -294,6 +369,7 @@ wxThread::~wxThread() // The default callback just joins the thread and throws away the result. void wxThread::OnExit() { + Join(); } // Automatic initialization @@ -301,16 +377,19 @@ class wxThreadModule : public wxModule { DECLARE_DYNAMIC_CLASS(wxThreadModule) public: virtual bool OnInit() { + wxMainMutex = new wxMutex(); wxThreadGuiInit(); p_mainid = pthread_self(); - wxMainMutex.Lock(); +// p_threads_list = wxList(wxKEY_INTEGER); + wxMainMutex->Lock(); return TRUE; } virtual void OnExit() { - wxMainMutex.Unlock(); + wxMainMutex->Unlock(); wxThreadGuiExit(); + delete wxMainMutex; } };