+static void ScheduleThreadForDeletion()
+{
+ wxMutexLocker lock( *gs_mutexDeleteThread );
+
+ gs_nThreadsBeingDeleted++;
+
+ wxLogTrace(TRACE_THREADS, wxT("%lu thread%s waiting to be deleted"),
+ (unsigned long)gs_nThreadsBeingDeleted,
+ gs_nThreadsBeingDeleted == 1 ? wxT("") : wxT("s"));
+}
+
+static void DeleteThread(wxThread *This)
+{
+ wxLogTrace(TRACE_THREADS, wxT("Thread %p auto deletes."), THR_ID(This));
+
+ delete This;
+
+ // only lock gs_mutexDeleteThread after deleting the thread to avoid
+ // calling out into user code with it locked as this may result in
+ // deadlocks if the thread dtor deletes another thread (see #11501)
+ wxMutexLocker locker( *gs_mutexDeleteThread );
+
+ wxCHECK_RET( gs_nThreadsBeingDeleted > 0,
+ wxT("no threads scheduled for deletion, yet we delete one?") );
+
+ wxLogTrace(TRACE_THREADS, wxT("%lu threads remain scheduled for deletion."),
+ (unsigned long)gs_nThreadsBeingDeleted - 1);
+
+ if ( !--gs_nThreadsBeingDeleted )
+ {
+ // no more threads left, signal it
+ gs_condAllDeleted->Signal();
+ }
+}
+
+#ifndef __WXOSX__
+
+void wxMutexGuiEnterImpl()