prevent double closing of handles
[TortoiseGit.git] / src / Git / SharedMutex.cpp
blobb7bce54577c5ac1b5768d291bdb19087afc5dc74
1 /**
2 * SharedMutex.cpp
3 * @Author Tu Yongce <yongce (at) 126 (dot) com>
4 * @Created 2008-11-17
5 * @Modified 2008-11-17
6 * @Version 0.1
7 */
8 #include "StdAfx.h"
9 #include "SharedMutex.h"
12 SharedMutex::SharedMutex(): m_sharedNum(0), m_exclusiveNum(0), m_lockType(LOCK_NONE), m_mutex(0), m_sharedEvent(0),m_exclusiveEvent(0)
17 SharedMutex::~SharedMutex()
22 void SharedMutex::Release()
24 if (m_mutex)
26 ::CloseHandle(m_mutex);
27 m_mutex = NULL;
29 if (m_sharedEvent)
31 ::CloseHandle(m_sharedEvent);
32 m_sharedEvent = NULL;
34 if (m_exclusiveEvent)
36 ::CloseHandle(m_exclusiveEvent);
37 m_exclusiveEvent = NULL;
40 void SharedMutex::Init()
42 m_sharedNum = m_exclusiveNum = 0;
43 m_lockType = LOCK_NONE;
45 // ´´½¨ÓÃÓÚ±£»¤ÄÚ²¿Êý¾ÝµÄ»¥³âÁ¿
46 m_mutex = ::CreateMutex(NULL, FALSE, NULL);
47 // ´´½¨ÓÃÓÚͬ²½¹²Ïí·ÃÎÊÏ̵߳Äʼþ£¨ÊÖ¶¯Ê¼þ£©
48 m_sharedEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
49 // ´´½¨ÓÃÓÚͬ²½¶ÀÕ¼·ÃÎÊÏ̵߳Äʼþ£¨×Ô¶¯Ê¼þ£©
50 m_exclusiveEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
53 // »ñÈ¡¹²Ïí·ÃÎÊȨ
54 bool SharedMutex::AcquireShared(DWORD waitTime)
56 ::WaitForSingleObject(m_mutex, INFINITE);
57 ++m_sharedNum;
58 if (m_lockType == LOCK_EXCLUSIVE) {
59 DWORD retCode = ::SignalObjectAndWait(m_mutex, m_sharedEvent, waitTime, FALSE);
60 if (retCode == WAIT_OBJECT_0) {
61 return true;
62 } else {
63 if (retCode == WAIT_TIMEOUT)
64 ::SetLastError(WAIT_TIMEOUT);
65 return false;
68 m_lockType = LOCK_SHARED;
69 ::ReleaseMutex(m_mutex);
70 return true;
73 // ÊͷŹ²Ïí·ÃÎÊȨ
74 void SharedMutex::ReleaseShared()
76 //assert(m_lockType == LOCK_SHARED);
77 ::WaitForSingleObject(m_mutex, INFINITE);
78 --m_sharedNum;
79 if (m_sharedNum == 0) {
80 if (m_exclusiveNum > 0) {
81 // »½ÐÑÒ»¸ö¶ÀÕ¼·ÃÎÊÏß³Ì
82 m_lockType = LOCK_EXCLUSIVE;
83 ::SetEvent(m_exclusiveEvent);
84 } else {
85 // ûÓеȴýÏß³Ì
86 m_lockType = LOCK_NONE;
89 ::ReleaseMutex(m_mutex);
92 // »ñÈ¡¶ÀÕ¼·ÃÎÊȨ
93 bool SharedMutex::AcquireExclusive(DWORD waitTime)
96 ::WaitForSingleObject(m_mutex, INFINITE);
97 ++m_exclusiveNum;
98 if (m_lockType != LOCK_NONE) {
99 DWORD retCode = ::SignalObjectAndWait(m_mutex, m_exclusiveEvent, waitTime, FALSE);
100 if (retCode == WAIT_OBJECT_0) {
101 return true;
102 } else {
103 if (retCode == WAIT_TIMEOUT)
104 ::SetLastError(WAIT_TIMEOUT);
105 return false;
108 m_lockType = LOCK_EXCLUSIVE;
109 ::ReleaseMutex(m_mutex);
110 return true;
113 // ÊͷŶÀÕ¼·ÃÎÊȨ
114 void SharedMutex::ReleaseExclusive()
116 // assert(m_lockType == LOCK_EXCLUSIVE);
117 ::WaitForSingleObject(m_mutex, INFINITE);
118 --m_exclusiveNum;
119 // ¶ÀÕ¼·ÃÎÊÏß³ÌÓÅÏÈ
120 if (m_exclusiveNum > 0) {
121 // »½ÐÑÒ»¸ö¶ÀÕ¼·ÃÎÊÏß³Ì
122 ::SetEvent(m_exclusiveEvent);
123 } else if (m_sharedNum > 0) {
124 // »½Ðѵ±Ç°ËùÓй²Ïí·ÃÎÊÏß³Ì
125 m_lockType = LOCK_SHARED;
126 ::PulseEvent(m_sharedEvent);
127 } else {
128 // ûÓеȴýÏß³Ì
129 m_lockType = LOCK_NONE;
131 ::ReleaseMutex(m_mutex);