自己寫的線程池類(使用C++,pure API,Mutex,Event)

來源:互聯網
上載者:User

電腦網路實驗要求寫一個檔案傳輸程式。由於以前自己寫的線程類和SOCKET類丟失掉了(寢室電腦被盜),現在重寫這幾個類,乾脆就寫了一個線程池,用的是C++STL和純API。而且,為了保證這個線程類本身是安全執行緒的,我還使用了WinApi中的互斥量。同時仿照C#的類庫,線上程類中加入了Join方法。調用線程對象Join方法的線程將等待線程對象直到執行完畢。以下是原始碼。

/////////////////////////////////MyThread.h//////////////////////////////////////

#ifndef _MYTHREAD_H_
#define _MYTHREAD_H_
#include "MyException.h"
#include <windows.h>
#include <list>
using namespace std;

//前向聲明
class CMyThread;//線程類
class CMyThreadPool;//線程池類
class CMyThreadExp;//線程異常類

#define MyThreadProc LPTHREAD_START_ROUTINE

//線程狀態枚舉
enum MyThreadStatus
{
 THREADRUN,//運行
 THREADPAUSE,//暫停
};
//線程類,可動態更換執行函數
class CMyThread
{
 struct MyThreadParam
 {
  LPTHREAD_START_ROUTINE proc;//使用者線程函數
  void *lpParam;//使用者線程參數
  CMyThread *pCMyThread;//線程類對象
 };
public:
 //構造,proc線程函數
 CMyThread();
 //析構
 ~CMyThread();
 //運行線程
 bool Run();
 //暫停線程
 bool Pause();
 //調用Join的線程將阻塞,直到該線程執行完畢
 void Join();
 //設定線程啟動並執行函數,和要傳給線程的參數
 void SetProc(LPTHREAD_START_ROUTINE proc, void* lpParam);

protected:
 CMyThread(CMyThread&) {}
 //線程實際啟動並執行函數
 static DWORD WINAPI RealThreadProc(void* lpParam);
 friend class CMyThreadPool;

protected:
 HANDLE m_hThread;
 DWORD m_id;
 HANDLE m_hEvt;
 MyThreadParam m_param;
 MyThreadStatus m_status;
 HANDLE m_hMtx;
};

//線程池類
class CMyThreadPool
{
public:
 //構造,initNum初始情況線程數量
 CMyThreadPool(int initNum);
 //析構
 ~CMyThreadPool();
 //申請線程進行工作,proc工作函數,lpParam工作函數參數,run是否立即運行,返回線程ID
 DWORD DoWork(LPTHREAD_START_ROUTINE proc, void *lpParam, bool run=true);
 //運行線程,id線程ID
 bool Run(DWORD id);
 //暫停運行線程,id線程ID
 bool Pause(DWORD id);
 //調整線程池大小為size,返回調整後線程池大小
 unsigned SetSize(unsigned size);//when decrease num, its dangerous

protected:
 list<CMyThread*> m_lst;
};

//線程異常種類枚舉
enum EnumMyThreadExp
{
 EXPCREATETHREAD = 0,
 EXPTERMINATETHREAD,
 EXPRESUMETHREAD,
 EXPSUSPENDTHREAD,
 EXPCREATEEVENT,
 EXPCREATEMUTEX,
};
//線程異常類
class CMyThreadExp : public CMyException
{
public:
 CMyThreadExp(EnumMyThreadExp exp, CMyThread *pobj);
 ~CMyThreadExp();
 void GetInfo();
 EnumMyThreadExp m_exp;
 CMyThread *m_pobj;
};

#endif//_MYTHREAD_H_

//////////////////////MyThread.cpp//////////////////////////////////

#include "mythread.h"
#include <iostream>
using namespace std;

CMyThreadExp::CMyThreadExp(EnumMyThreadExp exp, CMyThread *pobj)
: m_exp(exp), m_pobj(pobj)
{
 GetInfo();
 ShowExp();
}
CMyThreadExp::~CMyThreadExp()
{
}
void CMyThreadExp::GetInfo()
{
 sprintf(m_strInfo, "/nCMyThread Exception When %p Execute ", (void*)(m_pobj));
 switch (m_exp)
 {
 case EXPCREATETHREAD: strcat(m_strInfo, "CreateThread()"); break;
 case EXPTERMINATETHREAD: strcat(m_strInfo,"TerminateThread()"); break;
 case EXPRESUMETHREAD: strcat(m_strInfo, "ResumeThread()"); break;
 case EXPSUSPENDTHREAD: strcat(m_strInfo, "SuspendThread()"); break;
 case EXPCREATEEVENT: strcat(m_strInfo, "CreateEvent()"); break;
 case EXPCREATEMUTEX: strcat(m_strInfo, "CreateMutex()"); break;
 }
 char temp[100];
 sprintf(temp, "/nError Code = %d", GetLastError());
 strcat(m_strInfo, temp);
}
/**********************************************************************************************/
CMyThread::CMyThread()
: m_hThread(NULL), m_status(THREADPAUSE), m_hEvt(0), m_hMtx(0)
{
 m_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)(CMyThread::RealThreadProc),
      (void*)&m_param, CREATE_SUSPENDED, &m_id);
 if (m_hThread == NULL)//fail to create thread
 {
  CMyThreadExp(EXPCREATETHREAD, this);
  throw;//construct exception
 }
 m_param.proc = NULL;
 m_param.lpParam = NULL;
 m_param.pCMyThread = this;

 m_hEvt = CreateEvent(0, FALSE, FALSE, 0);//自動複位
 if (m_hEvt == 0)
 {
  CloseHandle(m_hThread);
  CMyThreadExp(EXPCREATEEVENT, this);
  throw;//construct exception
 }
 m_hMtx = CreateMutex(0, 0, 0);
 if (m_hMtx == 0)//fail to create mutex
 {
  unsigned long i = GetLastError();
  CloseHandle(m_hEvt);
  CloseHandle(m_hThread);
  CMyThreadExp(EXPCREATEMUTEX, this);
  throw;//construct exception
 }
}
CMyThread::~CMyThread()
{
 CloseHandle(m_hMtx);
 if (TerminateThread(m_hThread, -1) == 0)//fail to terminate
  CMyThreadExp(EXPTERMINATETHREAD, this);
}
bool CMyThread::Run()
{
 WaitForSingleObject(m_hMtx, INFINITE);//get mutex
 if (m_status == THREADPAUSE)
  if (ResumeThread(m_hThread) == -1)//fail to resume
  {
   CMyThreadExp(EXPRESUMETHREAD, this);
   ReleaseMutex(m_hMtx);//release mutex
   return false;
  }
 m_status = THREADRUN;
 ReleaseMutex(m_hMtx);//release mutex
 return true;
}
bool CMyThread::Pause()
{
 WaitForSingleObject(m_hMtx, INFINITE);//get mutex
 if (m_status == THREADRUN)
  if (SuspendThread(m_hThread) == -1)//fail to suspend
  {
   CMyThreadExp(EXPSUSPENDTHREAD, this);
   ReleaseMutex(m_hMtx);//release mutex
   return false;
  }
 m_status = THREADPAUSE;
 ReleaseMutex(m_hMtx);//release mutex
 return true;
}
void CMyThread::Join()
{
 WaitForSingleObject(m_hEvt, INFINITE);
}
void CMyThread::SetProc(LPTHREAD_START_ROUTINE proc, void* lpParam)
{
 WaitForSingleObject(m_hMtx, INFINITE);//get mutex
 m_param.proc = proc;
 m_param.lpParam = lpParam;
 ReleaseMutex(m_hMtx);//release mutex
}
DWORD WINAPI CMyThread::RealThreadProc(void* lpParam)
{
 LPTHREAD_START_ROUTINE proc;
 MyThreadParam *pp = (MyThreadParam*)lpParam;
 while (true)
 {
  proc = pp->proc;
  if (proc)
   (*proc)(pp->lpParam);
  pp->proc = NULL;//clear function
  pp->lpParam = NULL;//clear param
  pp->pCMyThread->Pause();//pause automatic
  SetEvent(pp->pCMyThread->m_hEvt);
 }
}
/**********************************************************************************************/
CMyThreadPool::CMyThreadPool(int initNum)
{
 CMyThread *pt;
 for (int i=0; i<initNum; i++)
 {
  pt = new CMyThread;
  m_lst.push_back(pt);
 }
}
CMyThreadPool::~CMyThreadPool()
{
 list<CMyThread*>::iterator it = m_lst.begin();
 list<CMyThread*>::iterator ite = m_lst.end();
 for ( ; it != ite; it++)//terminate all thread
 {
  delete (*it);
 }
}
DWORD CMyThreadPool::DoWork(LPTHREAD_START_ROUTINE proc, void *lpParam, bool run)
{
 list<CMyThread*>::iterator it = m_lst.begin();
 list<CMyThread*>::iterator ite = m_lst.end();
 for ( ; it != ite; it++)//is there a idle thread?
 {
  if ((*it)->m_param.proc == NULL
   && (*it)->m_status == THREADPAUSE
   )
  {
   (*it)->SetProc(proc, lpParam);
   if (run)//run at once
    (*it)->Run();
   return (*it)->m_id;
  }
 }
 //no idle thread
 CMyThread *pt = new CMyThread;//create a new thread
 m_lst.push_back(pt);
 pt->SetProc(proc, lpParam);
 if (run)
  pt->Run();
 return pt->m_id;
}
bool CMyThreadPool::Run(DWORD id)
{
 list<CMyThread*>::iterator it = m_lst.begin();
 list<CMyThread*>::iterator ite = m_lst.end();
 for ( ; it != ite; it++)
 {
  if ((*it)->m_id == id)
   return ((*it)->Run());
 }
 return false;
}
bool CMyThreadPool::Pause(DWORD id)
{
 list<CMyThread*>::iterator it = m_lst.begin();
 list<CMyThread*>::iterator ite = m_lst.end();
 for ( ; it != ite; it++)
 {
  if ((*it)->m_id == id)
   return ((*it)->Pause());
 }
 return false;
}
unsigned CMyThreadPool::SetSize(unsigned size)
{
 unsigned nowsize = m_lst.size();
 if (nowsize <= size)
 {
  CMyThread *pt;
  unsigned inc = size-nowsize;
  for (unsigned i=0; i<inc; i++)
  {
   pt = new CMyThread;
   m_lst.push_back(pt);
  }
  return size;
 }
 else
 {
  unsigned dec = nowsize - size;
  list<CMyThread*>::iterator it = m_lst.begin();
  list<CMyThread*>::iterator ite = m_lst.end();
  list<CMyThread*>::iterator itemp;
  unsigned i=0;
  for ( ; it!=ite && i<dec; )
  {
   if ((*it)->m_status == THREADPAUSE)
   {
    itemp = it++;
    delete ((*itemp));
    m_lst.erase(itemp);
    i++;
    continue;
   }
   it++;
  }
  Sleep(100*i);
  return m_lst.size();
 }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.