多線程實現代碼行數統計

  1. //文件類型  
  2. enum E_FILETYPE   
  3. {  
  4.     E_C,  
  5.     E_JAVA  
  6. };  
  7.   
  8. //文件行數信息  
  9. struct T_CodeFileMsg  
  10. {  
  11.     int nTaskId;                //任務Id  
  12.     string FileName;            //文件名稱  
  13.     E_FILETYPE eFiletype;       //文件類型  
  14.     int nTotalLine;             //總行數  
  15.     int nEmptyLine;             //空行數  
  16.     int nCodeLine;              //代碼行數  
  17.     int nNoteLine;              //註釋行數  
  18.     T_CodeFileMsg()  
  19.     {  
  20.         nTotalLine = 0;  
  21.         nEmptyLine = 0;  
  22.         nCodeLine = 0;  
  23.         nNoteLine = 0;  
  24.     }  
  25. };  
  26.   
  27.   
  28. #define MAX_WORKTHREAD      5       //線程最大數  
  29. #define MAX_LEN             1024    //路徑最大長度  
  30. #define MAX_CHAR            1024    //一行最大字符數  

  1. //線程函數  
  2. DWORD WINAPI ReadFileThread(LPVOID lpParam);    
  3. DWORD WINAPI WorkThread(LPVOID lpParam);   
  4.   
  5. //線程句柄  
  6. DWORD g_dwReadFileThreadID;    
  7. DWORD g_dwTaskThread;  
  8. DWORD g_dwWorkThread[MAX_WORKTHREAD];  
  9.   
  10. //事件句柄  
  11. HANDLE g_EventReadFileHandle;  
  12. HANDLE g_EventReadFinishHandle;  
  13.   
  14. //臨界區  
  15. CRITICAL_SECTION g_cs;  
  16. CRITICAL_SECTION g_MsgQueue;  
  17. CRITICAL_SECTION g_task;  
  18. CRITICAL_SECTION g_MsgMap;  
  19.   
  20.   
  21. //數據  
  22. map<intint>m_task;  
  23. std::deque<int> m_MsgQueue;  
  24. std::deque<int> m_FileQueue;//任務隊列  
  25. std::map<int, T_CodeFileMsg*> m_FileMsgMap;//處理文件與文件行數信息  
  26.   
  27. int WorkThreadCout = 0;  
  28. int nTotalTaskCount =0;  
  29. int nWorkTaslCount=0;  
  30. int nTaskBeginTime;  
  31. int nReadFileFinish=0;  
  32. int nInitCount= 0;  
  33. int nWorkFlag = 0;  
  34. bool bRunFlag = TRUE;  
  35. char g_workPath[MAX_LEN];  
  36.   
  37. bool bReadFileFlag=TRUE;  
  38.   
  39. int g_nTaskId=0;  
  40.   
  41.   
  42. int main()  
  43. {   
  44.     int i;  
  45.     cout << "#####代碼行數統計測試開始#####" <<endl;  
  46.   
  47.     cout << "Main thread is running." << endl;    
  48.       
  49.     //初始化臨界區  
  50.     InitializeCriticalSection(&g_cs);  
  51.     InitializeCriticalSection(&g_MsgQueue);  
  52.     InitializeCriticalSection(&g_MsgMap);  
  53.       
  54.     g_EventReadFileHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);  
  55.     g_EventReadFinishHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);  
  56.       
  57.     //創建線程  
  58.     HANDLE hRFTHandle = CreateThread(NULL, 0, ReadFileThread, NULL, 0, &g_dwReadFileThreadID);    
  59.       
  60.     HANDLE hWTHandle[MAX_WORKTHREAD];  
  61.       
  62.     for (i=0; i<MAX_WORKTHREAD; i++)  
  63.     {  
  64.         int* nTemp = new int;//如果不new,最後打印出來的WorkThread(LPVOID lpParam)的都是10  
  65.                                 //nTemp = &i;和*nTemp = i;區別。  
  66.         *nTemp = i;  
  67.         hWTHandle[i] = CreateThread(NULL, 0, WorkThread, nTemp, 0, &g_dwWorkThread[i]);   
  68.         WorkThreadCout ++;  
  69.         m_task[i] = 0;  
  70.         Sleep(100);  
  71.     }  
  72.       
  73.     while (TRUE)  
  74.     {  
  75.           
  76.         if (nWorkFlag == 0)  
  77.         {  
  78.             printf("輸入要統計文件的路徑或end退出\n");  
  79.             scanf("%s", g_workPath);  
  80.   
  81.   
  82.             DeleteMap();  
  83.             g_nTaskId = 0;  
  84.             nWorkTaslCount = 0;  
  85.               
  86.             if (strcmp(g_workPath, "end") == 0)  
  87.             {  
  88.                 bReadFileFlag = FALSE;//讀文件線程標誌  
  89.                 SetEvent(g_EventReadFileHandle);//讀事件  
  90.                 bRunFlag = FALSE;//讓線程退出  
  91.                 break;  
  92.             }  
  93.               
  94.             SetEvent(g_EventReadFileHandle);//讀事件  
  95.               
  96.             nWorkFlag = 1;  
  97.         }  
  98.   
  99.         ResetEvent(g_EventReadFinishHandle);  
  100.         WaitForSingleObject(g_EventReadFinishHandle, INFINITE);  
  101.   
  102.         if (nReadFileFinish == 1)  
  103.         {  
  104.             PrintMsg();  
  105.         }  
  106.     }  
  107.       
  108.     Sleep(3000);  
  109.   
  110.     DeleteMap();  
  111.       
  112.     CloseHandle(hRFTHandle);  
  113.     for (i=0; i<MAX_WORKTHREAD; i++)  
  114.     {  
  115.         CloseHandle(hWTHandle[i]);  
  116.     }  
  117.       
  118.     CloseHandle(g_EventReadFileHandle);     
  119.     CloseHandle(g_EventReadFinishHandle);    
  120.       
  121.     DeleteCriticalSection(&g_cs);  
  122.     DeleteCriticalSection(&g_MsgQueue);  
  123.     DeleteCriticalSection(&g_MsgMap);  
  124.       
  125.       
  126.     cout << "Main thread is end." << endl;  
  127.       
  128.     cout << "#####代碼行數統計測試結束#####" <<endl;  
  129.     //system("pause");    
  130.     return 0;    
  131. }  
  132.   
  133. int InitData()  
  134. {  
  135.     return 0;  
  136. }  
  137.   
  138. int DeleteMap()  
  139. {  
  140.     std::map<int, T_CodeFileMsg*>::iterator IterFile;  
  141.     for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++)  
  142.     {  
  143.         T_CodeFileMsg* file = (*IterFile).second;  
  144.   
  145.         delete file;  
  146.         file = NULL;  
  147.     }  
  148.   
  149.     m_FileMsgMap.clear();  
  150.   
  151.     return 0;  
  152. }  
  153.   
  154. DWORD WINAPI ReadFileThread(LPVOID lpParam)    
  155. {     
  156.     // cout << "No." << g_dwThreadID << " thread is running." << endl;    
  157.     while (bRunFlag)    
  158.     {    
  159.         EnterCriticalSection(&g_cs);  
  160.         cout << "ReadFileThread " << g_dwReadFileThreadID << " thread is running." << endl;  
  161.         LeaveCriticalSection(&g_cs);  
  162.           
  163.         ResetEvent(g_EventReadFileHandle);  
  164.         WaitForSingleObject(g_EventReadFileHandle, INFINITE);  
  165.         if (bReadFileFlag)  
  166.         {  
  167.             int nTemp = DirectoryList(g_workPath);//nReadFileFinish  
  168.             nReadFileFinish = nTemp;  
  169.             if (nTemp == 1)  
  170.             {  
  171.                 PrintFile();  
  172.                 nWorkFlag = 0;  
  173.                 nTotalTaskCount = g_nTaskId;  
  174.             }  
  175.             else  
  176.             {  
  177.                 nWorkFlag = 0;  
  178.             }  
  179.   
  180.             SetEvent(g_EventReadFinishHandle);  
  181.         }  
  182.           
  183.         Sleep(1000);  
  184.     }    
  185.       
  186.     cout << "ReadFileThread " << g_dwReadFileThreadID << " end" << endl;  
  187.       
  188.     return 0;    
  189. }   
  190.   
  191. DWORD WINAPI WorkThread(LPVOID lpParam)    
  192. {     
  193.     // cout << "No." << g_dwThreadID << " thread is running." << endl;    
  194.   
  195.     int* nRemp = (int*)lpParam;  
  196.     while (bRunFlag)    
  197.     {    
  198.         int n = -1;  
  199.         T_CodeFileMsg* pCFMsg=NULL;  
  200.           
  201.         EnterCriticalSection(&g_cs);  
  202.         //cout << "No " << *nRemp << ", " << g_dwWorkThread[*nRemp] << " thread is running." << endl;  
  203.         LeaveCriticalSection(&g_cs);  
  204.           
  205.         EnterCriticalSection(&g_MsgQueue);  
  206.         if (!m_FileQueue.empty())  
  207.         {  
  208.             n = m_FileQueue.front();  
  209.             m_FileQueue.pop_front();  
  210.             if (nWorkTaslCount == 0)  
  211.             {  
  212.                 nTaskBeginTime = GetTickCount();  
  213.             }  
  214.             nWorkTaslCount++;  
  215.               
  216.             m_task[*nRemp]++;  
  217.         }  
  218.   
  219.         LeaveCriticalSection(&g_MsgQueue);  
  220.           
  221.         EnterCriticalSection(&g_MsgMap);  
  222.         if ( n>= 0)//沒有這個,在開始的時候n=-1會造成溢出。  
  223.             pCFMsg = m_FileMsgMap[n];  
  224.         LeaveCriticalSection(&g_MsgMap);  
  225.   
  226.         EnterCriticalSection(&g_cs);  
  227.         //cout << "No:" << *nRemp << ", " << n << endl;  
  228.         if (pCFMsg!=NULL)  
  229.         {  
  230.             cout << pCFMsg->FileName.c_str() << endl;  
  231.         }  
  232.         LeaveCriticalSection(&g_cs);  
  233.   
  234.         if (pCFMsg!=NULL && n>=0)  
  235.         {  
  236.             ProcessFile(pCFMsg, n);  
  237.             Sleep(20);  
  238.         }  
  239.         else  
  240.             Sleep(2000);      
  241.     }   
  242.       
  243.     delete nRemp;  
  244.     nRemp = NULL;  
  245.       
  246.     cout << "No " << lpParam << " end" << endl;  
  247.       
  248.     return 0;    
  249. }  
  250.   
  251. //根據文件類型處理  
  252. int ProcessFile(T_CodeFileMsg* pTCFMsg, int n)  
  253. {  
  254.     EnterCriticalSection(&g_MsgMap);  
  255.     string tempFile = pTCFMsg->FileName;  
  256.     E_FILETYPE c_type = pTCFMsg->eFiletype;  
  257.     LeaveCriticalSection(&g_MsgMap);  
  258.   
  259.     switch(c_type)  
  260.     {  
  261.     case E_C:  
  262.         ProcessCFile(pTCFMsg, tempFile.c_str(), n);  
  263.         break;  
  264.     case E_JAVA:  
  265.         ProcessJavaFile(pTCFMsg, tempFile.c_str(), n);  
  266.         break;  
  267.     default:  
  268.         break;  
  269.     }  
  270.   
  271.     return 0;  
  272. }  
  273.   
  274. int ProcessCFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n)  
  275. {  
  276.     ifstream in;  
  277.     char buf[MAX_CHAR] = {0};  
  278.     bool bNoteFlag = FALSE;  
  279.     int nNoteLine = 0;  
  280.     int nEmptyLine = 0;  
  281.     int nCodeLine = 0;  
  282.     int nTotalLine = 0;  
  283.   
  284.     in.open(strFile);  
  285.     while(in.getline(buf, sizeof(buf)))   
  286.     {  
  287.         nTotalLine++;  
  288.         char* p = buf;   
  289.         while((*p ==' ' || *p=='\t')) p++;  
  290.   
  291.         if (!bNoteFlag)  
  292.         {  
  293.             if (*p == 0)  
  294.             {  
  295.                 nEmptyLine++;  
  296.                 cout << nTotalLine <<endl;  
  297.   
  298.             }  
  299.             else if (strncmp(p, "/*", 2)==0)   
  300.             {  
  301.                 char* q = buf+strlen(buf)-1;  
  302.                 while((*q ==' ' || *q=='\t')) q--;  
  303.                   
  304.                 q--;  
  305.   
  306.                 //判斷是不是/*AAA*/  
  307.                 if (strncmp(q, "*/", 2)==0)  
  308.                 {  
  309.                 }  
  310.                 else  
  311.                     bNoteFlag = TRUE;  
  312.   
  313.                 nNoteLine++;  
  314.                 cout << nTotalLine <<endl;  
  315.             }  
  316.             else if (strncmp(p, "//", 2)==0)   
  317.             {  
  318.                 nNoteLine++;  
  319.                 cout << nTotalLine <<endl;  
  320.             }  
  321.             else  
  322.             {  
  323.                 nCodeLine++;  
  324.             }  
  325.         }  
  326.         else  
  327.         {  
  328.             if (*p == 0)  
  329.             {  
  330.                 nNoteLine++;  
  331.                 cout << nTotalLine <<endl;  
  332.             }  
  333.             else if (strncmp(p, "*/", 2)==0)   
  334.             {  
  335.                 bNoteFlag = FALSE;  
  336.                 nNoteLine++;  
  337.                 cout << nTotalLine <<endl;  
  338.             }  
  339.             else   
  340.             {  
  341.                 nNoteLine++;  
  342.                 cout << nTotalLine <<endl;  
  343.   
  344.                 char* q = buf+strlen(buf)-1;  
  345.                 while((*q ==' ' || *q=='\t')) q--;  
  346.                   
  347.                 q--;  
  348.                   
  349.                 if (strncmp(q, "*/", 2)==0)  
  350.                 {  
  351.                     bNoteFlag = FALSE;  
  352.                 }  
  353.             }  
  354.         }  
  355.   
  356.         memset(buf, 0, MAX_CHAR);  
  357.     }  
  358.   
  359.     EnterCriticalSection(&g_MsgMap);  
  360.     pTCFMsg->nCodeLine = nCodeLine;  
  361.     pTCFMsg->nEmptyLine = nEmptyLine;  
  362.     pTCFMsg->nNoteLine = nNoteLine;  
  363.     pTCFMsg->nTotalLine = nTotalLine;  
  364.     m_FileMsgMap[n] = pTCFMsg;  
  365.     LeaveCriticalSection(&g_MsgMap);  
  366.   
  367.     return 0;  
  368. }  
  369.   
  370. int ProcessJavaFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n)  
  371. {  
  372.     return 0;  
  373. }  
  374.   
  375. int AddFile2Map(char* pFile)  
  376. {  
  377.     string strFile = strlwr(pFile);  
  378.       
  379.     int nRet = strFile.find(".", 0);  
  380.       
  381.     if (nRet>0)  
  382.     {  
  383.         string Temp;  
  384.         int nLen = strFile.size();  
  385.         Temp = strFile.substr(nRet, strFile.size()-nRet);  
  386.           
  387.         if (strcmp(Temp.c_str(),".c")==0 || strcmp(Temp.c_str(),".cpp")==0 || strcmp(Temp.c_str(),".h")==0)  
  388.         {         
  389.             T_CodeFileMsg* pTemp = new T_CodeFileMsg;  
  390.             m_FileMsgMap[g_nTaskId] = pTemp;  
  391.   
  392.             //m_FileMsgMap[g_nTaskId] = new T_CodeFileMsg;  
  393.             //T_CodeFileMsg* pTemp = m_FileMsgMap[g_nTaskId];  
  394.             pTemp->eFiletype = E_C;  
  395.             pTemp->nTaskId = g_nTaskId;  
  396.             pTemp->FileName = pFile;  
  397.             //pTemp->FileName = new char[nLen+1];  
  398.             //memcpy(pTemp->FileName, strFile.c_str(), nLen);  
  399.   
  400.               
  401.   
  402.             //m_FileMsgMap[g_nTaskId] = pTemp;  
  403.             //m_FileMsgMap.insert(pair <int, T_CodeFileMsg* >(g_nTaskId, pTemp));  
  404.             m_FileQueue.push_back(g_nTaskId);  
  405.             g_nTaskId++;  
  406.         }  
  407.   
  408.     }  
  409.     return 0;  
  410. }  
  411.   
  412. int DirectoryList(LPCSTR Path)  
  413. {  
  414.     WIN32_FIND_DATA FindData;  
  415.     HANDLE hError;  
  416.     int FileCount = 0;  
  417.     char FilePathName[MAX_LEN];  
  418.     // 構造路徑  
  419.     char FullPathName[MAX_LEN];  
  420.     strcpy(FilePathName, Path);  
  421.     strcat(FilePathName, "\\*.*");  
  422.     hError = FindFirstFile(FilePathName, &FindData);  
  423.     if (hError == INVALID_HANDLE_VALUE)  
  424.     {  
  425.         printf("搜索失敗!\n");  
  426.         return 0;  
  427.     }  
  428.       
  429.     while(::FindNextFile(hError, &FindData))  
  430.     {  
  431.         // 過慮.和..  
  432.         if (strcmp(FindData.cFileName, ".") == 0  
  433.             || strcmp(FindData.cFileName, "..") == 0 )  
  434.         {  
  435.             continue;  
  436.         }  
  437.           
  438.         // 構造完整路徑  
  439.         wsprintf(FullPathName, "%s\\%s", Path,FindData.cFileName);  
  440.         FileCount++;  
  441.           
  442.         AddFile2Map(FullPathName);  
  443.           
  444.         // 輸出本級的文件  
  445.         //printf("\n%d  %s  ", FileCount, FullPathName);  
  446.           
  447.         if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  
  448.         {  
  449.             //printf("<Dir>");  
  450.             DirectoryList(FullPathName);  
  451.         }             
  452.     }  
  453.       
  454.     return 1;  
  455.       
  456. }  
  457.   
  458. int PrintFile()  
  459. {  
  460.     EnterCriticalSection(&g_MsgMap);      
  461.     std::map<int, T_CodeFileMsg*>::iterator IterFile;  
  462.     for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++)  
  463.     {  
  464.         T_CodeFileMsg* file = (*IterFile).second;  
  465.           
  466.         //EnterCriticalSection(&g_cs);  
  467.         cout << endl;  
  468.         cout << file->FileName.c_str();  
  469.         cout << ", id:" << file->nTaskId;  
  470.         cout << ", nCodeLine:"<< file->nCodeLine;  
  471.         cout << ", nEmptyLine:"<< file->nEmptyLine;  
  472.         cout << ", nNoteLine:"<< file->nNoteLine;  
  473.         cout << ", nTotalLine:"<< file->nTotalLine;  
  474.         //LeaveCriticalSection(&g_cs);  
  475.           
  476.     }  
  477.     LeaveCriticalSection(&g_MsgMap);  
  478.   
  479.     return 0;  
  480. }  
  481.   
  482. int PrintMsg()  
  483. {  
  484.     while (TRUE)  
  485.     {  
  486.         if (nWorkTaslCount == nTotalTaskCount)  
  487.         {  
  488.             std::map<intint>::iterator IterCount;  
  489.             for(IterCount=m_task.begin(); IterCount!=m_task.end();IterCount++)  
  490.             {  
  491.                 int nThreadId= (*IterCount).first;  
  492.                 int nCount = (*IterCount).second;  
  493.                   
  494.                 EnterCriticalSection(&g_cs);  
  495.                 cout << "nThreadId:" << nThreadId << ", nCount:" << nCount<<endl;  
  496.                 LeaveCriticalSection(&g_cs);  
  497.                   
  498.                 (*IterCount).second = 0;  
  499.             }  
  500.               
  501.             nWorkFlag = 0;  
  502.               
  503.             PrintFile();  
  504.   
  505.             break;  
  506.         }  
  507.   
  508.         cout << "nWorkTaslCount:" << nWorkTaslCount << ", nTotalTaskCount:" << nTotalTaskCount <<endl;  
  509.           
  510.         Sleep(1000);  
  511.     }  
  512.       
  513.     return 0;  
  514. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章