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.


Related articles: