C++ implements multithreading to find file instances
- 2020-04-02 02:53:11
- OfStack
Mainly multithreaded mutex file lookup
A framework for mutual exclusion of multiple threads
//Thread function & NBSP; < br / >
UINT FinderEntry(LPVOID lpParam)
{
//The CRapidFinder is passed in as a parameter & NBSP; & have spent < br / >
CRapidFinder* pFinder = (CRapidFinder*)lpParam;
CDirectoryNode* pNode = NULL;
BOOL bActive = TRUE; //BActive is TRUE, indicating that the current thread is active & NBSP; < br / >
//The loop handles the directory & PI in the m_listDir list; < br / >
while (1)
{
//Take a directory & NBSP; from the list; < br / >
::EnterCriticalSection(&pFinder->m_cs);
if (pFinder->m_listDir.IsEmpty()) //The directory list is empty, the current thread is not activated, so bAactive = FALSE < br / >
{
bActive = FALSE;
}
else
{
pNode = pFinder->m_listDir.GetHead(); //Get a catalogue & NBSP; < br / >
pFinder->m_listDir.Remove(pNode); //Remove & NBSP; from the directory list; < br / >
}
::LeaveCriticalSection(&pFinder->m_cs);
//If the current thread is stopped & NBSP; < br / >
if (bActive == FALSE)
{
//Stop the current thread & NBSP; < br / >
//The number of threads, & have spent < br / >
pFinder->m_nThreadCount--;
//If the number of currently active threads is 0, bounces, ends & NBSP; < br / >
if (pFinder->m_nThreadCount == 0)
{
::LeaveCriticalSection(&pFinder->m_cs);
break;
}
::LeaveCriticalSection(&pFinder->m_cs);
//The number of active threads is not 0, waiting for other threads to add a directory & NBSP to the directory list; < br / >
::ResetEvent(pFinder->m_hDirEvent);
::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);
//At this point, the other thread wakes up the thread. < br / >
pFinder->m_nThreadCount++; //Activates its own thread, number of threads ++& NBSP; < br / >
bActive = TRUE; //The current thread is alive & NBSP; < br / >
continue; //Jump to the while, & have spent < br / >
}
//Successfully obtained the directory & NBSP; from the directory list; < br / >
<span style="white-space:pre"> </span>......................
//if (pNode)
//{
// delete pNode;
// pNode = NULL;
//}
}//end while
//Causes a search thread to return from WaitForSingleObject and exit the loop & NBSP; < br / >
::SetEvent(pFinder->m_hDirEvent);
//Determines if the thread is the last one to end the loop, and if so, notifies the main thread & NBSP; < br / >
if (::WaitForSingleObject(pFinder->m_hDirEvent,0) != WAIT_TIMEOUT)
{
::SetEvent(pFinder->m_hExitEvent);
}
return 1;
}
Find the file frame:
//Successfully obtained the directory & NBSP; from the directory list; < br / >
WIN32_FIND_DATA fileData;
HANDLE hFindFile;
//Generates the correct lookup string & NBSP; < br / >
if (pNode->szDir[strlen(pNode->szDir)-1] != '\')
{
strcat(pNode->szDir,"\");
}
strcat(pNode->szDir, "*.*");
//Find the frame of the file & NBSP; < br / >
hFindFile = ::FindFirstFile(pNode->szDir, &fileData);
if (hFindFile != INVALID_HANDLE_VALUE )
{
do
{
//If it's the current directory, skip & NBSP; < br / >
if (fileData.cFileName[0] == '.')
{
continue;
}
//If it's a catalogue & NBSP; < br / >
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//Adds the current directory to the directory list & NBSP; < br / >
.
//Causes a thread to become active from an inactive state & NBSP; < br / >
::SetEvent(pFinder->m_hDirEvent);
}
else //If it's a document & NBSP; < br / >
{
.
}
} while (::FindNextFile(hFindFile, &fileData));
}
All code main.cpp:
#include "RapidFinder.h"
#include <stddef.h>
#include <stdio.h>
#include <process.h>
//M_nMaxThread is of type const int and can only be initialized in this way & NBSP; < br / >
CRapidFinder::CRapidFinder(int nMaxThread):m_nMaxThread(nMaxThread)
{
m_nResultCount = 0;
m_nThreadCount = 0;
m_listDir.Construct(offsetof(CDirectoryNode, pNext)); //Offsetof in the stddef.h header file & NBSP; < br / >
::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)
{
//Define two strings & PI; < br / >
char string[MAX_PATH];
char strSearch[MAX_PATH];
strcpy(string, lpszFileName);
strcpy(strSearch, m_szMatchName);
//Capitalize the string & NBSP; < br / >
_strupr(string);
_strupr(strSearch);
//Compare the string with strsearch&cake; < br / >
if (strstr(string, strSearch) != NULL)
{
return TRUE;
}
return FALSE;
}
//Thread function & NBSP; < br / >
UINT FinderEntry(LPVOID lpParam)
{
//The CRapidFinder is passed in as a parameter & NBSP; & have spent < br / >
CRapidFinder* pFinder = (CRapidFinder*)lpParam;
CDirectoryNode* pNode = NULL;
BOOL bActive = TRUE; //BActive is TRUE, indicating that the current thread is active & NBSP; < br / >
//The loop handles the directory & PI in the m_listDir list; < br / >
while (1)
{
//Take a directory & NBSP; from the list; < br / >
::EnterCriticalSection(&pFinder->m_cs);
if (pFinder->m_listDir.IsEmpty()) //The directory list is empty, the current thread is not activated, so bAactive = FALSE < br / >
{
bActive = FALSE;
}
else
{
pNode = pFinder->m_listDir.GetHead(); //Get a catalogue & NBSP; < br / >
pFinder->m_listDir.Remove(pNode); //Remove & NBSP; from the directory list; < br / >
}
::LeaveCriticalSection(&pFinder->m_cs);
//If the current thread is stopped & NBSP; < br / >
if (bActive == FALSE)
{
//Stop the current thread & NBSP; < br / >
::EnterCriticalSection(&pFinder->m_cs);
pFinder->m_nThreadCount--;
//If the number of currently active threads is 0, bounces, ends & NBSP; < br / >
if (pFinder->m_nThreadCount == 0)
{
::LeaveCriticalSection(&pFinder->m_cs);
break;
}
::LeaveCriticalSection(&pFinder->m_cs);
//The number of active threads is not 0, waiting for other threads to add a directory & NBSP to the directory list; < br / >
::ResetEvent(pFinder->m_hDirEvent);
::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);
//At this point, the other threads add a new directory & NBSP; to the directory list. < br / >
::EnterCriticalSection(&pFinder->m_cs);
pFinder->m_nThreadCount++; //Activates its own thread, number of threads ++& NBSP; < br / >
::LeaveCriticalSection(&pFinder->m_cs);
bActive = TRUE; //The directory is no longer empty & NBSP; < br / >
continue; //Skip to while and retrieve the directory & NBSP; from the list of directories; < br / >
}
//Successfully obtained the directory & NBSP; from the directory list; < br / >
WIN32_FIND_DATA fileData;
HANDLE hFindFile;
//Generates the correct lookup string & NBSP; < br / >
if (pNode->szDir[strlen(pNode->szDir)-1] != '\')
{
strcat(pNode->szDir,"\");
}
strcat(pNode->szDir, "*.*");
//Find the frame of the file & NBSP; < br / >
hFindFile = ::FindFirstFile(pNode->szDir, &fileData);
if (hFindFile != INVALID_HANDLE_VALUE )
{
do
{
//If it's the current directory, skip & NBSP; < br / >
if (fileData.cFileName[0] == '.')
{
continue;
}
//If it's a catalogue & NBSP; < br / >
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//Adds the current directory to the directory list & NBSP; < br / >
CDirectoryNode* p = new CDirectoryNode;
strncpy(p->szDir, pNode->szDir, strlen(pNode->szDir)-3); //Remove the *.* bits after pNode & NBSP; < br / >
strcat(p->szDir, fileData.cFileName);
::EnterCriticalSection(&pFinder->m_cs);
pFinder->m_listDir.AddHead(p);
::LeaveCriticalSection(&pFinder->m_cs);
//Now p is added to the list, delete, it's bound to cause an error & sponge; < br / >
//delete p;
//p = NULL;
//Causes a thread to become active from an inactive state & NBSP; < br / >
::SetEvent(pFinder->m_hDirEvent);
}
else //If it's a document & NBSP; < br / >
{
//Determines whether it is the file to look for & NBSP; & have spent < br / >
if (pFinder->CheckFile(fileData.cFileName)) //Document & NBSP; a match lookup; & have spent < br / >
{
//Print & have spent < br / >
::EnterCriticalSection(&pFinder->m_cs);
pFinder->m_nResultCount++;
::LeaveCriticalSection(&pFinder->m_cs);
printf("find %d:%sn", pFinder->m_nResultCount, fileData.cFileName);
}
}
} while (::FindNextFile(hFindFile, &fileData));
}
//if (pNode)
//{
// delete pNode;
// pNode = NULL;
//}
}//end while
//Causes a search thread to return from WaitForSingleObject and exit the loop & NBSP; < br / >
::SetEvent(pFinder->m_hDirEvent);
//Determines if the thread is the last one to end the loop, and if so, notifies the main thread & NBSP; < br / >
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;
//Start multi-threading & NBSP; < br / >
for (int i=0;i< pFinder->m_nMaxThread;i++)
{
::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FinderEntry, pFinder, 0, NULL);
}
//The main program resumes running only if m_hExitEvent is trusted < br / >
::WaitForSingleObject(pFinder->m_hExitEvent,INFINITE);
printf(" A total of find %dn", pFinder->m_nResultCount);
//if (pNode != NULL) delete pNode;
if (pFinder != NULL) delete pFinder;
getchar();
return;
}
The rapidfinder.h file is as follows:
#include "_AFXTLS_.H"
struct CDirectoryNode: public CNoTrackObject
{
CDirectoryNode* pNext;
char szDir[MAX_PATH];
};
class CRapidFinder
{
public:
CRapidFinder(int nMaxThread); //Constructor & NBSP; < br / >
virtual ~CRapidFinder(); //Destructor & NBSP; < br / >
BOOL CheckFile(LPCTSTR lpszFileName); //Check that lpszFileName matches the search criteria & noon; < br / >
int m_nResultCount; //Number of results found & NBSP; < br / >
int m_nThreadCount; //Current number of threads & NBSP; < br / >
CTypedSimpleList<CDirectoryNode*> m_listDir; //Find the directory & NBSP; < br / >
CRITICAL_SECTION m_cs; //Sharing & have spent < br / >
const int m_nMaxThread; //Maximum number of threads & NBSP; < br / >
char m_szMatchName[MAX_PATH]; //The name you are looking for & NBSP; < br / >
HANDLE m_hDirEvent; //Add a new directory post & NBSP; < br / >
HANDLE m_hExitEvent; //Settings & NBSP when all threads exit; < br / >
};
The following two classes implement the simplelist class and template
_afxatl. CPP file:
#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 file:
#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);
//Members needed to implement the interface & NBSP; < br / >
void* m_pHead;
int m_nNextOffset;
void** GetNextPtr(void* p) const;
};
//The inline function of the class & NBSP; < br / >
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
Hope that the article described in the C++ programming to help you.