/** ManagedThread : A managed implementation of wxThreads
* (c) 2005, Ricardo Garcia
* (Developed as an auxiliary library
* for project "Code::Blocks" by Yiannis Mandravelos)
* This file is distributed under the wxWindows license
*/
#include "sdk_precomp.h"
#include "managedthread.h"
#include <wx/utils.h>
/// Keeps count of running threads
wxMutex ManagedThread::s_count_running_mutex;
wxMutex ManagedThread::s_list_mutex;
unsigned long ManagedThread::s_running = 0;
bool ManagedThread::s_abort_all = false;
static ManagedThreadsArray s_threadslist;
ManagedThread::ManagedThread(bool* abortflag) :
wxThread(wxTHREAD_JOINABLE),
m_pAbort(abortflag)
{
wxMutexLocker* lock;
lock = new wxMutexLocker(s_list_mutex);
s_threadslist.Add(this);
delete lock;
}
ManagedThread::~ManagedThread()
{
// wxMutexLocker* lock;
// lock = new wxMutexLocker(s_list_mutex);
// NOTE: DeleteThreadFromList() locks the mutex by itself
DeleteThreadFromList(this); // Deletes thread from list
// delete lock;
}
unsigned long ManagedThread::count_running()
{
wxMutexLocker lock(ManagedThread::s_count_running_mutex);
return ManagedThread::s_running;
}
unsigned long ManagedThread::count_threads()
{
wxMutexLocker lock(ManagedThread::s_list_mutex);
return s_threadslist.GetCount();
}
ManagedThread* ManagedThread::GetThread(size_t n)
{
wxMutexLocker lock(ManagedThread::s_list_mutex);
if(n>=s_threadslist.GetCount())
return 0L;
return s_threadslist.Item(n);
}
void ManagedThread::abort_all()
{
// 1) Send signal to threads telling to terminate ASAP
if(count_running() > 0)
{
ManagedThread::s_abort_all = true;
while(count_running() > 0)
{
#if wxVERSION_NUMBER < 2500
wxUsleep(5);
#else
wxMilliSleep(5);
#endif
}
#if wxVERSION_NUMBER < 2500
wxUsleep(50);
#else
wxMilliSleep(50);
#endif
// (there's a tiny delay between the thread disminishing the count
// and the thread actually stopping)
// 50 ms should be more than enough
}
// 2) Delete thread objects
ManagedThread *thread;
for(unsigned int i = 0; i < count_threads();++i)
{
thread = GetThread(i);
if(thread)
{
if(thread->IsAlive())
{ thread->Delete(); }
delete thread;
}
}
// 3) Clear thread list
wxMutexLocker lock(ManagedThread::s_list_mutex);
s_threadslist.Clear();
// 4) Reset the abort flag now that no threads are running
ManagedThread::s_abort_all = false;
}
void ManagedThread::abort(bool* flag,bool delete_thread)
{
if(!flag)
return;
// 1) Send signal to threads telling to terminate ASAP
if(count_running() > 0)
{
*flag = true;
#if wxVERSION_NUMBER < 2500
wxUsleep(50); // Wait for threads to terminate
#else
wxMilliSleep(50);
#endif
}
// 2) Delete thread objects
ManagedThread *thread;
for(unsigned int i = 0; i < count_threads();++i)
{
thread = GetThread(i);
if(!thread)
continue;
if(thread->get_abort_location()!=flag)
continue;
if(thread->IsAlive())
{ thread->Delete(); }
if(delete_thread)
delete thread;
}
// 4) Reset the abort flag now that no associated threads are running
*flag = false;
}
void* ManagedThread::Entry()
{
void* result;
wxMutexLocker* lock;
lock = new wxMutexLocker(s_count_running_mutex);
s_running++;
delete lock;
result = DoRun();
lock = new wxMutexLocker(s_count_running_mutex);
if(s_running > 0)
s_running--;
delete lock;
return result;
}
void* ManagedThread::DoRun()
{ return 0; }
void ManagedThread::DeleteThreadFromList(ManagedThread* thread)
{
wxMutexLocker lock(ManagedThread::s_list_mutex);
unsigned int i = 0;
while(i < s_threadslist.GetCount())
{
if(s_threadslist[i]==thread)
{
s_threadslist.RemoveAt(i,1);
}
else
++i;
}
}
bool ManagedThread::TestDestroy()
{
return is_aborted() || wxThread::TestDestroy();
}
bool ManagedThread::is_aborted()
{
if(ManagedThread::s_abort_all)
return true;
if(m_pAbort)
return (*m_pAbort);
return false;
}
syntax highlighted by Code2HTML, v. 0.9.1