📄 cthread.cpp.svn-base
字号:
/* Agobot3 - a modular IRC bot for Win32 / Linux
Copyright (C) 2003 Ago
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "main.h"
#include "cthread.h"
#include "mainctrl.h"
// I cna cdoe 800 sytnxa rerros pre mniuet!!!
// Volatile pthreads refcount
int volatile g_iRefCount=0;
#ifndef WIN32
// Global that is set if PThreads is initialized
bool g_bPThreadsInited=false;
#endif // WIN32
// Number of threads currently running
int volatile g_iNumThreads=0;
CThread::CThread() {
// Set the dynamic state to false
m_bDynamic=true;
m_bRunning=false;
m_bRestart=false;
m_szType="CThread";
CThread::InitPThreads();
}
CThread::~CThread() {
try {
// Kill the thread in case its still running
if(m_bRunning)
{
m_bRunning=false;
m_mRunning.Unlock();
#ifdef WIN32
TerminateThread(m_hThread, 1);
#else
// Join the thread
pthread_join(m_tThread, NULL);
#endif // WIN32
}
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CThread::~CThread(cthread.cpp): Kill() caused an exception.\n");
#endif // DBGCONSOLE
}
CThread::CleanupPThreads();
}
void CThread::InitPThreads() {
if(!g_iRefCount) {
// pthread_win32_process_attach_np();
// pthread_win32_thread_attach_np();
// g_bPThreadsInited=true;
g_iRefCount++;
}
else
g_iRefCount++;
}
void CThread::CleanupPThreads() {
if(g_iRefCount>1)
g_iRefCount--;
else {
g_iRefCount--;
// pthread_win32_process_detach_np();
// pthread_win32_thread_detach_np();
}
}
bool CThread::Start(bool bDynamic, bool bRestart, bool bRealtime) {
m_bDynamic=bDynamic; m_bRestart=bRestart;
try {
#ifdef WIN32
m_hThread=CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&this->RunWrapper, this, 0, &m_dwThreadId);
if(m_hThread)
{ m_mRunning.Lock(); m_bRunning=true; return true; }
else
{ m_mRunning.Unlock(); m_bRunning=false; return false; }
#else
if(!pthread_create(&m_tThread, NULL, &this->RunWrapper, this))
{ m_mRunning.Lock(); m_bRunning=true; return true; }
else
{ m_mRunning.Unlock(); m_bRunning=false; return false; }
#endif // WIN32
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CThread::Start(cthread.cpp): pthread_create caused an exception.\n");
#endif // DBGCONSOLE
m_mRunning.Unlock(); m_bRunning=false; return false;
}
}
void CThread::Kill() {
Join();
}
int CThread::Join() {
try {
// Join the thread
if(m_bRunning) {
m_bRunning=false; m_bRestart=false;
#ifdef WIN32
return TerminateThread(m_hThread, 1);
#else
return pthread_join(m_tThread, NULL);
#endif // WIN32
} else return 0;
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CThread::Join(cthread.cpp): Exception thrown (%s).\n", m_szType);
#endif // DBGCONSOLE
}
return 0; }
void *CThread::RunWrapper(void *pArgs) {
CThread *pThread=(CThread*)pArgs;
while(true)
{
try {
g_iNumThreads++;
// Call the pure virtual of the thread function
pThread->Run();
g_iNumThreads--;
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
g_iNumThreads--;
#ifdef DBGCONSOLE
if(g_pMainCtrl) {
if(pThread->m_bRestart)
if(pThread->m_szType)
g_pMainCtrl->m_cConsDbg.Log(2, "CThread::RunWrapper(cthread.cpp): %s thread caused an exception, restarting.\n", pThread->m_szType);
else
g_pMainCtrl->m_cConsDbg.Log(2, "CThread::RunWrapper(cthread.cpp): Unnamed thread caused an exception, restarting.\n");
else
g_pMainCtrl->m_cConsDbg.Log(2, "CThread::RunWrapper(cthread.cpp): Thread caused an exception, exiting.\n");
}
#endif // DBGCONSOLE
}
if(!pThread->m_bRestart) break;
}
#ifdef DBGCONSOLE
if(pThread->m_szType)
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CThread::RunWrapper(cthread.cpp): %s thread exiting (%d threads).\n", pThread->m_szType, g_iNumThreads);
else
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CThread::RunWrapper(cthread.cpp): Unnamed thread exiting (%d threads).\n", g_iNumThreads);
#endif // DBGCONSOLE
pThread->m_bRunning=false;
if(pThread->m_bDynamic) g_pCleanupThread->Schedule(pThread);
pThread->m_mRunning.Unlock();
return NULL;
}
CMutex::CMutex() {
#ifdef WIN32
m_bLocked=false;
#else
CThread::InitPThreads();
// Initialize the mutex
pthread_mutex_init(&m_mMutex, NULL);
#endif // WIN32
}
CMutex::~CMutex() {
#ifdef WIN32
m_bLocked=false;
#else
CThread::CleanupPThreads();
// Destroy the mutex
pthread_mutex_destroy(&m_mMutex);
#endif // WIN32
}
void CMutex::Lock() {
#ifdef WIN32
while(m_bLocked && g_pMainCtrl->m_bRunning) Sleep(500);
m_bLocked=true;
#else
// Lock the mutex
pthread_mutex_lock(&m_mMutex);
#endif // WIN32
}
void CMutex::Unlock() {
#ifdef WIN32
m_bLocked=false;
#else
// Unlock the mutex
pthread_mutex_unlock(&m_mMutex);
#endif // WIN32
}
CCleanupThread::CCleanupThread()
{
m_szType="CCleanupThread";
}
void *CCleanupThread::Run()
{ while((g_iRefCount || !m_lQueue.empty()) && m_bRunning && g_pMainCtrl->m_bRunning)
{ Cleanup(); Sleep(2000); }
return NULL; }
void CCleanupThread::Schedule(CThread *pThread)
{ if(pThread==this) return;
m_mLock.Lock();
try {
m_lQueue.push_back(pThread);
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CCleanupThread: Schedule() got invalid value 0x%.8X.\n", pThread);
#endif // DBGCONSOLE
}
m_mLock.Unlock(); }
void CCleanupThread::Cleanup()
{ try {
m_mLock.Lock(); list<CThread*>::reverse_iterator it;
for(it=m_lQueue.rbegin(); it!=m_lQueue.rend(); ++it)
{
CThread *pThread=(*it);
try {
bool bBla=pThread->m_bDynamic;
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CCleanupThread: Cleaning up \"%s\".\n", pThread->m_szType);
#endif // DBGCONSOLE
if(pThread->m_bDynamic) delete pThread;
else {
pThread->Kill();
pThread->Join();
}
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CCleanupThread: m_lQueue contained invalid value.\n");
#endif // DBGCONSOLE
}
}
m_lQueue.clear(); m_mLock.Unlock();
#ifdef PtW32CatchAll
} PtW32CatchAll {
#else
} catch(...) {
#endif
#ifdef DBGCONSOLE
if(g_pMainCtrl) g_pMainCtrl->m_cConsDbg.Log(2, "CCleanupThread: m_lQueue invalid.\n");
#endif // DBGCONSOLE
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -