* Added thread cleanup safeness: thread can be explicitely killed safely now

on Unix.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2467 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guilhem Lavaux 1999-05-15 12:01:15 +00:00
parent 92abe7f670
commit 5092b3add7
3 changed files with 428 additions and 357 deletions

722
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1437,6 +1437,18 @@ if test "$wxUSE_THREADS" = "1"; then
AC_DEFINE(HAVE_PTHREAD_CANCEL),
AC_MSG_WARN(wxThread::Kill() will not work properly))
AC_MSG_CHECKING([for pthread_cleanup_push/pop])
AC_TRY_COMPILE([#include <pthread.h>],
[
pthread_cleanup_push(NULL, NULL);
pthread_cleanup_pop(0);
],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_THREAD_CLEANUP_FUNCTIONS)
],
[AC_MSG_RESULT(no)]
)
THREADS_LINK="-l$THREADS_LINK"
fi

View File

@ -231,6 +231,11 @@ public:
// thread entry function
static void *PthreadStart(void *ptr);
#if HAVE_THREAD_CLEANUP_FUNCTIONS
// thread exit function
static void PthreadCleanup(void *ptr);
#endif
// thread actions
// start the thread
wxThreadError Run();
@ -289,6 +294,7 @@ void *wxThreadInternal::PthreadStart(void *ptr)
{
wxThread *thread = (wxThread *)ptr;
wxThreadInternal *pthread = thread->p_internal;
void *status;
int rc = pthread_setspecific(gs_keySelf, thread);
if ( rc != 0 )
@ -297,6 +303,10 @@ void *wxThreadInternal::PthreadStart(void *ptr)
return (void *)-1;
}
#if HAVE_THREAD_CLEANUP_FUNCTIONS
// Install the cleanup handler.
pthread_cleanup_push(wxThreadInternal::PthreadCleanup, ptr);
#endif
// wait for the condition to be signaled from Run()
// mutex state: currently locked by the thread which created us
@ -305,7 +315,11 @@ void *wxThreadInternal::PthreadStart(void *ptr)
// mutex state: locked again on exit of Wait()
// call the main entry
void* status = thread->Entry();
status = thread->Entry();
#if HAVE_THREAD_CLEANUP_FUNCTIONS
pthread_cleanup_pop(FALSE);
#endif
// terminate the thread
thread->Exit(status);
@ -315,6 +329,28 @@ void *wxThreadInternal::PthreadStart(void *ptr)
return NULL;
}
#if HAVE_THREAD_CLEANUP_FUNCTIONS
// Only called when the thread is explicitely killed.
void wxThreadInternal::PthreadCleanup(void *ptr)
{
wxThread *thread = (wxThread *) ptr;
// The thread is already considered as finished.
if (thread->p_internal->GetState() == STATE_EXITED)
return;
// first call user-level clean up code
thread->OnExit();
// next wake up the threads waiting for us (OTOH, this function won't retur
// until someone waited for us!)
thread->p_internal->SetState(STATE_EXITED);
thread->p_internal->SignalExit();
}
#endif
wxThreadInternal::wxThreadInternal()
{
m_state = STATE_NEW;
@ -367,9 +403,11 @@ void wxThreadInternal::Wait()
if ( wxThread::IsMain() )
wxMutexGuiLeave();
printf("Entering wait ...\n");
// entering Wait() releases the mutex thus allowing SignalExit() to acquire
// it and to signal us its termination
m_cond.Wait(m_mutex);
printf("Exiting wait ...\n");
// mutex is still in the locked state - relocked on exit from Wait(), so
// unlock it - we don't need it any more, the thread has already terminated
@ -382,18 +420,21 @@ void wxThreadInternal::Wait()
void wxThreadInternal::SignalExit()
{
printf("SignalExit\n");
// GL: Unlock mutexSuspend here.
m_mutexSuspend.Unlock();
// as mutex is currently locked, this will block until some other thread
// (normally the same which created this one) unlocks it by entering Wait()
m_mutex.Lock();
printf("Mutex acquired\n");
// wake up all the threads waiting for our termination
m_cond.Broadcast();
// after this call mutex will be finally unlocked
m_mutex.Unlock();
printf("Mutex unacquired\n");
}
void wxThreadInternal::Pause()
@ -672,16 +713,20 @@ void wxThread::Exit(void *status)
{
// first call user-level clean up code
OnExit();
printf(" ... OnExit()\n");
// next wake up the threads waiting for us (OTOH, this function won't return
// until someone waited for us!)
p_internal->SetState(STATE_EXITED);
p_internal->SignalExit();
printf(" ... SignalExit()\n");
p_internal->SetState(STATE_EXITED);
printf(" ... SetState()\n");
// delete both C++ thread object and terminate the OS thread object
// GL: This is very ugly and buggy ...
// delete this;
printf(" ... Exit\n");
pthread_exit(status);
}