主要是多线程的互斥 文件 的查找
多线程互斥的框架
//线程函数 UINT FinderEntry(LPVOID lpParam) { //CRapidFinder通过参数传递进来 CRapidFinder* pFinder = (CRapidFinder*)lpParam; CDirectoryNode* pNode = NULL; BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活 //循环处理m_listDir列表中的目录 while (1) { //从列表中取出一个目录 ::EnterCriticalSection(&pFinder->m_cs); if (pFinder->m_listDir.IsEmpty()) //目录列表为空,当前线程不激活,所以bAactive=FALSE { bActive = FALSE; } else { pNode = pFinder->m_listDir.GetHead(); //得到一个目录 pFinder->m_listDir.Remove(pNode); //从目录列表中移除 } ::LeaveCriticalSection(&pFinder->m_cs); //如果停止当前线程 if (bActive == FALSE) { //停止当前线程 //线程数-- pFinder->m_nThreadCount--; //如果当前活动线程数为0,跳出,结束 if (pFinder->m_nThreadCount == 0) { ::LeaveCriticalSection(&pFinder->m_cs); break; } ::LeaveCriticalSection(&pFinder->m_cs); //当前活动线程数不为0,等待其他线程向目录列表中加目录 ::ResetEvent(pFinder->m_hDirEvent); ::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE); //运行到这,就说明其他线程唤醒了本线程 pFinder->m_nThreadCount++; //激活了自己的线程,线程数++ bActive = TRUE; //当前线程活了 continue; //跳到while, } //从目录列表中成功取得了目录 <span style="white-space:pre"> </span>...................... //if (pNode) //{ // delete pNode; // pNode = NULL; //} }//end while //促使一个搜索线程从WaitForSingleObject返回,并退出循环 ::SetEvent(pFinder->m_hDirEvent); //判断此线程是否是最后一个结束循环的线程,如果是就通知主线程 if (::WaitForSingleObject(pFinder->m_hDirEvent,0) != WAIT_TIMEOUT) { ::SetEvent(pFinder->m_hExitEvent); } return 1; }
查找文件 的框架:
//从目录列表中成功取得了目录 WIN32_FIND_DATA fileData; HANDLE hFindFile; //生成正确的查找字符串 if (pNode->szDir[strlen(pNode->szDir)-1] != '\\') { strcat(pNode->szDir,"\\"); } strcat(pNode->szDir, "*.*"); //查找文件的框架 hFindFile = ::FindFirstFile(pNode->szDir, &fileData); if (hFindFile != INVALID_HANDLE_VALUE ) { do { //如果是当前目录,跳过 if (fileData.cFileName[0] == '.') { continue; } //如果是目录 if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //将当前目录加入到目录列表 。。。。。。 //使一个线程从非活动状态变成活动状态 ::SetEvent(pFinder->m_hDirEvent); } else //如果是文件 { 。。。。。。。。。。。。。 } } while (::FindNextFile(hFindFile, &fileData)); }
所有代码main.cpp:
#include "RapidFinder.h" #include <stddef.h> #include <stdio.h> #include <process.h> //m_nMaxThread 是const int类型,只能通过这种方式初始化 CRapidFinder::CRapidFinder(int nMaxThread):m_nMaxThread(nMaxThread) { m_nResultCount = 0; m_nThreadCount = 0; m_listDir.Construct(offsetof(CDirectoryNode, pNext)); //offsetof在stddef.h头文件中 ::InitializeCriticalSection(&m_cs); m_szMatchName[0] = '\0'; m_hDirEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); } CRapidFinder::~CRapidFinder() { ::DeleteCriticalSection(&m_cs); ::CloseHandle(m_hDirEvent); ::CloseHandle(m_hExitEvent); } BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName) { //定义两个字符串 char string[MAX_PATH]; char strSearch[MAX_PATH]; strcpy(string, lpszFileName); strcpy(strSearch, m_szMatchName); //将字符串大写 _strupr(string); _strupr(strSearch); //比较string中是否含有strSearch if (strstr(string, strSearch) != NULL) { return TRUE; } return FALSE; } //线程函数 UINT FinderEntry(LPVOID lpParam) { //CRapidFinder通过参数传递进来 CRapidFinder* pFinder = (CRapidFinder*)lpParam; CDirectoryNode* pNode = NULL; BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活 //循环处理m_listDir列表中的目录 while (1) { //从列表中取出一个目录 ::EnterCriticalSection(&pFinder->m_cs); if (pFinder->m_listDir.IsEmpty()) //目录列表为空,当前线程不激活,所以bAactive=FALSE { bActive = FALSE; } else { pNode = pFinder->m_listDir.GetHead(); //得到一个目录 pFinder->m_listDir.Remove(pNode); //从目录列表中移除 } ::LeaveCriticalSection(&pFinder->m_cs); //如果停止当前线程 if (bActive == FALSE) { //停止当前线程 ::EnterCriticalSection(&pFinder->m_cs); pFinder->m_nThreadCount--; //如果当前活动线程数为0,跳出,结束 if (pFinder->m_nThreadCount == 0) { ::LeaveCriticalSection(&pFinder->m_cs); break; } ::LeaveCriticalSection(&pFinder->m_cs); //当前活动线程数不为0,等待其他线程向目录列表中加目录 ::ResetEvent(pFinder->m_hDirEvent); ::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE); //运行到这,就说明其他线程向目录列表中加入了新的目录 ::EnterCriticalSection(&pFinder->m_cs); pFinder->m_nThreadCount++; //激活了自己的线程,线程数++ ::LeaveCriticalSection(&pFinder->m_cs); bActive = TRUE; //目录不再为空 continue; //跳到while,重新在目录列表中取目录 } //从目录列表中成功取得了目录 WIN32_FIND_DATA fileData; HANDLE hFindFile; //生成正确的查找字符串 if (pNode->szDir[strlen(pNode->szDir)-1] != '\\') { strcat(pNode->szDir,"\\"); } strcat(pNode->szDir, "*.*"); //查找文件的框架 hFindFile = ::FindFirstFile(pNode->szDir, &fileData); if (hFindFile != INVALID_HANDLE_VALUE ) { do { //如果是当前目录,跳过 if (fileData.cFileName[0] == '.') { continue; } //如果是目录 if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //将当前目录加入到目录列表 CDirectoryNode* p = new CDirectoryNode; strncpy(p->szDir, pNode->szDir, strlen(pNode->szDir)-3); //将pNode后面的*.*三位去掉 strcat(p->szDir, fileData.cFileName); ::EnterCriticalSection(&pFinder->m_cs); pFinder->m_listDir.AddHead(p); ::LeaveCriticalSection(&pFinder->m_cs); // 现在的p刚加入列表,就要delete,肯定会出错 //delete p; //p = NULL; //使一个线程从非活动状态变成活动状态 ::SetEvent(pFinder->m_hDirEvent); } else //如果是文件 { //判断是否为要查找的文件 if (pFinder->CheckFile(fileData.cFileName)) //符合查找的文件 { //打印 ::EnterCriticalSection(&pFinder->m_cs); pFinder->m_nResultCount++; ::LeaveCriticalSection(&pFinder->m_cs); printf("find %d:%s\n", pFinder->m_nResultCount, fileData.cFileName); } } } while (::FindNextFile(hFindFile, &fileData)); } //if (pNode) //{ // delete pNode; // pNode = NULL; //} }//end while //促使一个搜索线程从WaitForSingleObject返回,并退出循环 ::SetEvent(pFinder->m_hDirEvent); //判断此线程是否是最后一个结束循环的线程,如果是就通知主线程 if (::WaitForSingleObject(pFinder->m_hDirEvent,0) != WAIT_TIMEOUT) { ::SetEvent(pFinder->m_hExitEvent); } return 1; } void main() { printf("start:\n"); CRapidFinder* pFinder = new CRapidFinder(64); CDirectoryNode* pNode = new CDirectoryNode; char szPath[] = "c:\\"; char szFile[] = "config"; strcpy(pNode->szDir, szPath); pFinder->m_listDir.AddHead(pNode); strcpy(pFinder->m_szMatchName, szFile); pFinder->m_nThreadCount = pFinder->m_nMaxThread; //开始开启多线程 for (int i=0;i< pFinder->m_nMaxThread;i++) { ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FinderEntry, pFinder, 0, NULL); } //只有m_hExitEvent受信状态,主线程才恢复运行 ::WaitForSingleObject(pFinder->m_hExitEvent,INFINITE); printf("共找到%d\n", pFinder->m_nResultCount); //if (pNode != NULL) delete pNode; if (pFinder != NULL) delete pFinder; getchar(); return; }
rapidfinder.h文件如下:
#include "_AFXTLS_.H" struct CDirectoryNode: public CNoTrackObject { CDirectoryNode* pNext; char szDir[MAX_PATH]; }; class CRapidFinder { public: CRapidFinder(int nMaxThread); //构造函数 virtual ~CRapidFinder(); //析构函数 BOOL CheckFile(LPCTSTR lpszFileName); //检查lpszFileName是否符合查找条件 int m_nResultCount; //找到的结果数量 int m_nThreadCount; //当前的线程数量 CTypedSimpleList<CDirectoryNode*> m_listDir; //查找目录 CRITICAL_SECTION m_cs; //共享 const int m_nMaxThread; //最大线程数量 char m_szMatchName[MAX_PATH]; //要查找的名称 HANDLE m_hDirEvent; //添加新目录后置位 HANDLE m_hExitEvent; //所有线程退出时置位 };
下面这两个类就是实现了simplelist类和模板
_afxatl.cpp文件:
#include "_AFXTLS_.H" void CSimpleList::AddHead(void* p) { *GetNextPtr(p) = m_pHead; m_pHead = p; } BOOL CSimpleList::Remove(void* p) { if (p == NULL) { return FALSE; } BOOL bResult = FALSE; if (p == m_pHead) { m_pHead = *GetNextPtr(m_pHead); bResult = TRUE; } else { void* pTest = m_pHead; while (pTest != NULL && *GetNextPtr(pTest) != p) { pTest = *GetNextPtr(pTest); } if (pTest != NULL) { *GetNextPtr(pTest) = *GetNextPtr(p); bResult = TRUE; } } return bResult; } void* CNoTrackObject::operator new(size_t nSize) { void* p = ::GlobalAlloc(GPTR, nSize); return p; } void CNoTrackObject::operator delete(void* p) { if (p!=NULL) { ::GlobalFree(p); } }
afxatl.h文件:
#ifndef _AFXTLS_H_H #define _AFXTLS_H_H #include <Windows.h> class CSimpleList { public: CSimpleList(int nNextOffset=0); void Construct(int nNextOffset); BOOL IsEmpty() const; void AddHead(void* p); void RemoveAll(); void* GetHead() const; void* GetNext(void* p) const; BOOL Remove(void* p); //为实现接口所需要的成员 void* m_pHead; int m_nNextOffset; void** GetNextPtr(void* p) const; }; //类的内联函数 inline CSimpleList::CSimpleList(int nNextOffset) {m_pHead = NULL; m_nNextOffset = nNextOffset;} inline void CSimpleList::Construct(int nNextOffset) {m_nNextOffset = nNextOffset;} inline BOOL CSimpleList::IsEmpty() const {return m_pHead==NULL;} inline void CSimpleList::RemoveAll() {m_pHead=NULL;} inline void* CSimpleList::GetHead() const {return m_pHead;} inline void* CSimpleList::GetNext(void* preElement) const { return *GetNextPtr(preElement); } inline void** CSimpleList::GetNextPtr(void* p) const { return (void**)((BYTE*)p + m_nNextOffset); } class CNoTrackObject { public: void* operator new(size_t nSize); void operator delete(void*); virtual ~CNoTrackObject(){}; }; template<class TYPE> class CTypedSimpleList:public CSimpleList { public: CTypedSimpleList(int nNextOffset=0) :CSimpleList(nNextOffset){} void AddHead(TYPE p) { CSimpleList::AddHead((void*)p); } TYPE GetHead() { return (TYPE)CSimpleList::GetHead(); } TYPE GetNext(TYPE p) { return (TYPE)CSimpleList::GetNext((void*)p); } BOOL Remove(TYPE p) { return CSimpleList::Remove(p); } operator TYPE() { return (TYPE)CSimpleList::GetHead(); } }; #endif
希望本文所述对大家的C++程序设计有所帮助。