OSDN Git Service

Use safe back thread way to fetch log at GitLogList.
authorFrank Li <lznuaa@gmail.com>
Fri, 30 Jan 2009 02:55:47 +0000 (10:55 +0800)
committerFrank Li <lznuaa@gmail.com>
Fri, 30 Jan 2009 02:55:47 +0000 (10:55 +0800)
Use postmessage send message to main thread handle UI operation to avoid dead lock when use waitforsingle object when try to terminate back thread

Signed-off-by: Frank Li <lznuaa@gmail.com>
src/TortoiseProc/GitLogListBase.cpp
src/TortoiseProc/GitLogListBase.h
src/TortoiseProc/LogDlg.cpp
src/TortoiseProc/LogDlg.h
src/TortoiseProc/TortoiseProc.vcproj

index cc87122..500c9cf 100644 (file)
@@ -143,6 +143,7 @@ BEGIN_MESSAGE_MAP(CGitLogListBase, CHintListCtrl)
        ON_NOTIFY_REFLECT(LVN_ODFINDITEM,OnLvnOdfinditemLoglist)\r
        ON_WM_CREATE()\r
        ON_WM_DESTROY()\r
+       ON_MESSAGE(MSG_LOADED,OnLoad)\r
 END_MESSAGE_MAP()\r
 \r
 int CGitLogListBase:: OnCreate(LPCREATESTRUCT lpCreateStruct)\r
@@ -1384,7 +1385,10 @@ int CGitLogListBase::FillGitShortLog()
        \r
 \r
        //this->m_logEntries.ParserFromLog();\r
-       SetItemCountEx(this->m_logEntries.size());\r
+       if(IsInWorkingThread())\r
+               PostMessage(LVM_SETITEMCOUNT, (WPARAM) this->m_logEntries.size(),(LPARAM) LVSICF_NOINVALIDATEALL);\r
+       else\r
+               SetItemCountEx(this->m_logEntries.size());\r
 \r
        this->m_arShownList.RemoveAll();\r
 \r
@@ -1439,9 +1443,8 @@ void CGitLogListBase::OnNMDblclkLoglist(NMHDR * /*pNMHDR*/, LRESULT *pResult)
          DiffSelectedRevWithPrevious();\r
 }\r
 \r
-int CGitLogListBase::FetchLogAsync(CALLBACK_PROCESS *proc,void * data)\r
+int CGitLogListBase::FetchLogAsync(void * data)\r
 {\r
-       m_ProcCallBack=proc;\r
        m_ProcData=data;\r
        m_bExitThread=FALSE;\r
        InterlockedExchange(&m_bThreadRunning, TRUE);\r
@@ -1482,8 +1485,9 @@ void CGitLogListBase::GetTimeRange(CTime &oldest, CTime &latest)
 UINT CGitLogListBase::LogThread()\r
 {\r
 \r
-       if(m_ProcCallBack)\r
-               m_ProcCallBack(m_ProcData,GITLOG_START);\r
+//     if(m_ProcCallBack)\r
+//             m_ProcCallBack(m_ProcData,GITLOG_START);\r
+       ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_START,0);\r
 \r
        InterlockedExchange(&m_bThreadRunning, TRUE);\r
        InterlockedExchange(&m_bNoDispUpdates, TRUE);\r
@@ -1503,7 +1507,7 @@ UINT CGitLogListBase::LogThread()
        \r
        if(this->m_bExitThread)\r
                return 0;\r
-\r
+#if 0\r
        RedrawItems(0, m_arShownList.GetCount());\r
        SetRedraw(false);\r
        ResizeAllListCtrlCols();\r
@@ -1526,6 +1530,7 @@ UINT CGitLogListBase::LogThread()
                        SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);\r
                }\r
        }\r
+#endif\r
        InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
 \r
        int index=0;\r
@@ -1541,8 +1546,6 @@ UINT CGitLogListBase::LogThread()
                                if(!m_logEntries.FetchFullInfo(i))\r
                                {\r
                                        updated++;\r
-                                       this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
-                                       this->InvalidateRect(rect);\r
                                }\r
                                m_LogCache.AddCacheEntry(m_logEntries[i]);\r
 \r
@@ -1551,11 +1554,10 @@ UINT CGitLogListBase::LogThread()
                                updated++;\r
                                InterlockedExchange(&m_logEntries[i].m_IsUpdateing,FALSE);\r
                                InterlockedExchange(&m_logEntries[i].m_IsFull,TRUE);\r
-\r
-                               this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
-                               this->InvalidateRect(rect);\r
                        }\r
                        \r
+                       ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)i,0);\r
+\r
                        if(m_bExitThread)\r
                                return 0;\r
 \r
@@ -1563,8 +1565,7 @@ UINT CGitLogListBase::LogThread()
                        if(percent == GITLOG_END)\r
                                percent = GITLOG_END -1;\r
                        \r
-                       if(m_ProcCallBack)\r
-                               m_ProcCallBack(m_ProcData,percent);\r
+                       ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
 \r
                        \r
                }\r
@@ -1576,10 +1577,7 @@ UINT CGitLogListBase::LogThread()
        // make sure the filter is applied (if any) now, after we refreshed/fetched\r
        // the log messages\r
 \r
-       \r
-\r
-       if(m_ProcCallBack)\r
-               m_ProcCallBack(m_ProcData,GITLOG_END);\r
+       ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_END,0);\r
 \r
        InterlockedExchange(&m_bThreadRunning, FALSE);\r
 \r
@@ -1880,6 +1878,13 @@ void CGitLogListBase::Clear()
 \r
 void CGitLogListBase::OnDestroy()\r
 {\r
+       if(this->m_bThreadRunning)\r
+       {\r
+               this->m_bExitThread=true;\r
+               DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);\r
+               if(ret == WAIT_TIMEOUT)\r
+                       TerminateThread();\r
+       }\r
        while(m_LogCache.SaveCache())\r
        {\r
                if(CMessageBox::Show(NULL,_T("Can Save Log Cache to Disk,click yes for retry, click no for give up"),_T("TortoiseGit"),\r
@@ -1887,4 +1892,13 @@ void CGitLogListBase::OnDestroy()
                                                        break;\r
        }\r
        CHintListCtrl::OnDestroy();\r
-}
\ No newline at end of file
+}\r
+\r
+LRESULT CGitLogListBase::OnLoad(WPARAM wParam,LPARAM lParam)\r
+{\r
+       CRect rect;\r
+       int i=(int)wParam;\r
+       this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
+       this->InvalidateRect(rect);\r
+       return 0;\r
+}\r
index 9b27658..9d0dc18 100644 (file)
@@ -53,7 +53,9 @@ enum LISTITEMSTATES_MINE {
 #define LOGFILTER_REGEX           6\r
 #define LOGFILTER_BUGID    7\r
 \r
-typedef void CALLBACK_PROCESS(void * data, int progress);\r
+//typedef void CALLBACK_PROCESS(void * data, int progress);\r
+#define MSG_LOADED                             (WM_USER+110)\r
+#define MSG_LOAD_PERCENTAGE            (WM_USER+111)\r
 \r
 class CGitLogListBase : public CHintListCtrl\r
 {\r
@@ -136,7 +138,7 @@ public:
        int  FillGitLog(CTGitPath *path,int infomask=CGit::     LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE);\r
 \r
        inline int ShownCountWithStopped() const { return (int)m_arShownList.GetCount() + (m_bStrictStopped ? 1 : 0); }\r
-       int FetchLogAsync(CALLBACK_PROCESS *proc=NULL, void * data=NULL);\r
+       int FetchLogAsync(void * data=NULL);\r
        CPtrArray                       m_arShownList;\r
        void Refresh();\r
        void RecalculateShownList(CPtrArray * pShownlist);\r
@@ -167,6 +169,11 @@ public:
                if(this->m_LoadingThread)\r
                        AfxTermThread((HINSTANCE)m_LoadingThread->m_hThread);\r
        };\r
+\r
+       bool IsInWorkingThread()\r
+       {\r
+               return (AfxGetThread() == m_LoadingThread);\r
+       }\r
        \r
        volatile bool           m_bExitThread;\r
        CWinThread*                     m_LoadingThread;\r
@@ -177,6 +184,7 @@ protected:
        afx_msg void OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult);\r
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);\r
        afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);\r
+       afx_msg LRESULT OnLoad(WPARAM wParam, LPARAM lParam);\r
        void OnNMDblclkLoglist(NMHDR * /*pNMHDR*/, LRESULT *pResult);\r
        afx_msg void OnLvnOdfinditemLoglist(NMHDR *pNMHDR, LRESULT *pResult);\r
        void PreSubclassWindow();\r
@@ -213,7 +221,6 @@ protected:
        CRegDWORD                       m_regMaxBugIDColWidth;\r
        int                                     m_nSearchIndex;\r
        \r
-       CALLBACK_PROCESS    *m_ProcCallBack;\r
        void                            *m_ProcData;\r
        CStoreSelection*        m_pStoreSelection;\r
        MAP_HASH_NAME           m_HashMap;\r
index e2bb8a1..6e87056 100644 (file)
@@ -123,6 +123,8 @@ BEGIN_MESSAGE_MAP(CLogDlg, CResizableStandAloneDialog)
        \r
        ON_MESSAGE(WM_FILTEREDIT_INFOCLICKED, OnClickedInfoIcon)\r
        ON_MESSAGE(WM_FILTEREDIT_CANCELCLICKED, OnClickedCancelFilter)\r
+\r
+       ON_MESSAGE(MSG_LOAD_PERCENTAGE,OnLogListLoading)\r
        \r
        ON_EN_CHANGE(IDC_SEARCHEDIT, OnEnChangeSearchedit)\r
        ON_WM_TIMER()\r
@@ -349,14 +351,16 @@ BOOL CLogDlg::OnInitDialog()
        //m_tFrom = (DWORD)-1;\r
 \r
        m_LogList.m_Path=m_path;\r
-       m_LogList.FetchLogAsync(LogCallBack,this);\r
+       m_LogList.FetchLogAsync(this);\r
 \r
        GetDlgItem(IDC_LOGLIST)->SetFocus();\r
        return FALSE;\r
 }\r
 \r
-void CLogDlg::LogRunStatus(int cur)\r
+LRESULT CLogDlg::OnLogListLoading(WPARAM wParam, LPARAM lParam)\r
 {\r
+       int cur=(int)wParam;\r
+\r
        if( cur == GITLOG_START )\r
        {\r
                CString temp;\r
@@ -406,6 +410,7 @@ void CLogDlg::LogRunStatus(int cur)
        }\r
 \r
        m_LogProgress.SetPos(cur);\r
+       return 0;\r
 }\r
 void CLogDlg::SetDlgTitle(bool bOffline)\r
 {\r
@@ -616,48 +621,14 @@ void CLogDlg::GetAll(bool bForceAll /* = false */)
                SetWindowText(m_sTitle + _T(" - "));\r
                break;\r
        }\r
-       //m_LogList.m_bExitThread=TRUE;\r
-       //::WaitForSingleObject(m_LogList.m_LoadingThread->m_hThread,INFINITE);\r
-\r
-       m_LogList.TerminateThread();\r
+       m_LogList.m_bExitThread=TRUE;\r
+       DWORD ret =::WaitForSingleObject(m_LogList.m_LoadingThread->m_hThread,20000);\r
+       if(ret == WAIT_TIMEOUT)\r
+               m_LogList.TerminateThread();\r
        \r
        m_LogList.Clear();\r
-       m_LogList.FetchLogAsync(LogCallBack,this);\r
-#if 0\r
-       m_ChangedFileListCtrl.SetItemCountEx(0);\r
-       m_ChangedFileListCtrl.Invalidate();\r
-       // We need to create CStoreSelection on the heap or else\r
-       // the variable will run out of the scope before the\r
-       // thread ends. Therefore we let the thread delete\r
-       // the instance.\r
-       m_pStoreSelection = new CStoreSelection(this);\r
-       m_LogList.SetItemCountEx(0);\r
-       m_LogList.Invalidate();\r
-       InterlockedExchange(&m_bNoDispUpdates, TRUE);\r
-       CWnd * pMsgView = GetDlgItem(IDC_MSGVIEW);\r
-       pMsgView->SetWindowText(_T(""));\r
-\r
-       SetSortArrow(&m_LogList, -1, true);\r
-\r
-       m_LogList.DeleteAllItems();\r
-       m_arShownList.RemoveAll();\r
-       m_logEntries.ClearAll();\r
-\r
-       m_logcounter = 0;\r
-       m_bCancelled = FALSE;\r
-       m_tTo = 0;\r
-       m_tFrom = (DWORD)-1;\r
-       m_limit = 0;\r
+       m_LogList.FetchLogAsync(this);\r
 \r
-       InterlockedExchange(&m_bThreadRunning, TRUE);\r
-       if (AfxBeginThread(LogThreadEntry, this)==NULL)\r
-       {\r
-               InterlockedExchange(&m_bThreadRunning, FALSE);\r
-               CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
-       }\r
-       GetDlgItem(IDC_LOGLIST)->UpdateData(FALSE);\r
-       InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
-#endif\r
 }\r
 \r
 void CLogDlg::OnBnClickedRefresh()\r
index fa42a04..e03bb4a 100644 (file)
@@ -108,6 +108,8 @@ protected:
        afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam);\r
        afx_msg LRESULT OnClickedInfoIcon(WPARAM wParam, LPARAM lParam);\r
        afx_msg LRESULT OnClickedCancelFilter(WPARAM wParam, LPARAM lParam);\r
+       afx_msg LRESULT OnLogListLoading(WPARAM wParam, LPARAM lParam);\r
+\r
        afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);\r
        afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);\r
        afx_msg void OnBnClickedGetall();\r
index aaa2659..7fe42bb 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\explorer.ico"\r
+                               RelativePath=".\explorer.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\explorer.ico"\r
+                               RelativePath="..\Resources\explorer.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\newfolder.ico"\r
+                               RelativePath=".\newfolder.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\newfolder.ico"\r
+                               RelativePath="..\Resources\newfolder.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\open.ico"\r
+                               RelativePath=".\open.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\open.ico"\r
+                               RelativePath="..\Resources\open.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\save.ico"\r
+                               RelativePath=".\save.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\save.ico"\r
+                               RelativePath="..\Resources\save.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\saveas.ico"\r
+                               RelativePath=".\saveas.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\saveas.ico"\r
+                               RelativePath="..\Resources\saveas.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\up.ico"\r
+                               RelativePath=".\up.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\up.ico"\r
+                               RelativePath="..\Resources\up.ico"\r
                                >\r
                        </File>\r
                        <File\r