Listing 1 LocksMonitor class
#include <iostream.h> #include "LocksMonitor.h" #include "directedGraph.h" #include "locksLogger.h" #include <crtdbg.h> #include <winbase.h> // Messages proccesor DWORD WINAPI LocksMonitorThreadProc(LPVOID param) { CLocksMonitor locksMonitor; Edge threadEdge; Edge resourceEdge; MSG msg; threadEdge.m_bThread = true; resourceEdge.m_bThread = false; while (GetMessage(&msg, NULL, 0, WM_LM_INIT_MSG_QUEUE)) { threadEdge.m_hID = (HANDLE)msg.wParam; resourceEdge.m_hID = (HANDLE)msg.lParam; switch (msg.message) { case(WM_LM_TRY_LOCK): locksMonitor.TryLock(threadEdge, resourceEdge); break; case(WM_LM_OWN_LOCK): locksMonitor.OwnLock(threadEdge, resourceEdge); break; case(WM_LM_RELEASE_LOCK): locksMonitor.ReleaseLock(threadEdge, resourceEdge); break; case(WM_LM_INIT_MSG_QUEUE): // dummy message that is sent in order to create // a message queue for this thread break; default: // no operation break; } } return 0; } //------------------------------------------------------------------------------------------- void CLocksMonitor::TryLock(const Edge& thread, const Edge& resource) { if (m_directedGraph.InsertNode(thread, resource) == RC_NODE_ALREADY_EXIST) { m_logger.TryWhileOwn((DWORD)thread.m_hID, resource.m_hID); return; } if (m_directedGraph.IsCyclic(thread, resource, m_cycleList)) { AnalizeDeadlock(); BreakDeadlock(); m_cycleList.clear(); } } void CLocksMonitor::OwnLock(const Edge& thread, const Edge& resource) { m_directedGraph.ReverseNode(thread, resource); } void CLocksMonitor::ReleaseLock(const Edge& thread, const Edge& resource) { if (m_directedGraph.RemoveNode(resource, thread) == RC_NODE_NOT_EXIST) m_logger.ReleaseWithoutAquire((DWORD)thread.m_hID, resource.m_hID); } void CLocksMonitor::AnalizeDeadlock() { m_logger.DumpText("*** Detect deadlock. Dump stack of all threads in deadlock cycle ***"); for (list<Edge>::const_iterator listIter = m_cycleList.begin(); listIter != m_cycleList.end(); listIter++) { if ((*listIter).m_bThread) m_logger.DumpStack((DWORD)(*listIter).m_hID); } } void CLocksMonitor::BreakDeadlock() { // you should think of some clever alghoritm to decide about the victim // thread to be killed. I'll select it randomaly... for (list<Edge>::const_iterator listIter = m_cycleList.begin(); listIter != m_cycleList.end(); listIter++) { if ((*listIter).m_bThread) { HANDLE hThread = OpenThread(THREAD_TERMINATE, FALSE, (DWORD)(*listIter).m_hID); TerminateThread(hThread, 0); m_directedGraph.RemoveEdge(*listIter); m_logger.NotifyKill((DWORD)(*listIter).m_hID); CloseHandle(hThread); break; } } }