OSDN Git Service

Merge branch 'master' of git://repo.or.cz/TortoiseGit
[tortoisegit/TortoiseGitJp.git] / src / Utils / RWSection.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 #include "RWSection.h"\r
21 \r
22 CRWSection::CRWSection()\r
23 {\r
24         m_nWaitingReaders = m_nWaitingWriters = m_nActive = 0;\r
25         m_hReaders = CreateSemaphore(NULL, 0, MAXLONG, NULL);\r
26         m_hWriters = CreateSemaphore(NULL, 0, MAXLONG, NULL);\r
27         InitializeCriticalSection(&m_cs);\r
28 }\r
29 \r
30 CRWSection::~CRWSection()\r
31 {\r
32 #ifdef _DEBUG\r
33         if (m_nActive != 0)\r
34                 DebugBreak();\r
35 #endif\r
36 \r
37         m_nWaitingReaders = m_nWaitingWriters = m_nActive = 0;\r
38         DeleteCriticalSection(&m_cs);\r
39         CloseHandle(m_hWriters);\r
40         CloseHandle(m_hReaders);\r
41 }\r
42 \r
43 bool CRWSection::WaitToRead(DWORD waitTime)\r
44 {\r
45         EnterCriticalSection(&m_cs);\r
46 \r
47         // Writers have priority\r
48         BOOL fResourceWritePending = (m_nWaitingWriters || (m_nActive < 0));\r
49 \r
50         if (fResourceWritePending)\r
51         {\r
52                 m_nWaitingReaders++;\r
53         } \r
54         else \r
55         {\r
56                 m_nActive++;\r
57         }\r
58 \r
59         LeaveCriticalSection(&m_cs);\r
60 \r
61         if (fResourceWritePending)\r
62         {\r
63                 // wait until writer is finished\r
64                 if (WaitForSingleObject(m_hReaders, waitTime) != WAIT_OBJECT_0)\r
65                 {\r
66                         EnterCriticalSection(&m_cs);\r
67                         m_nWaitingReaders--;\r
68                         LeaveCriticalSection(&m_cs);\r
69                         return false;\r
70                 }\r
71         }\r
72         return true;\r
73 }\r
74 \r
75 bool CRWSection::WaitToWrite(DWORD waitTime)\r
76 {\r
77         EnterCriticalSection(&m_cs);\r
78 \r
79         BOOL fResourceOwned = (m_nActive != 0);\r
80 \r
81         if (fResourceOwned)\r
82         {\r
83                 m_nWaitingWriters++;\r
84         } \r
85         else \r
86         {\r
87                 m_nActive = -1;\r
88         }\r
89 \r
90         LeaveCriticalSection(&m_cs);\r
91 \r
92         if (fResourceOwned)\r
93         {\r
94                 if (WaitForSingleObject(m_hWriters, waitTime) != WAIT_OBJECT_0)\r
95                 {\r
96                         EnterCriticalSection(&m_cs);\r
97                         m_nWaitingWriters--;\r
98                         LeaveCriticalSection(&m_cs);\r
99                         return false;\r
100                 }\r
101         }\r
102         return true;\r
103 }\r
104 \r
105 void CRWSection::Done()\r
106 {\r
107         EnterCriticalSection(&m_cs);\r
108 \r
109         if (m_nActive > 0)\r
110         {\r
111                 m_nActive--;\r
112         }\r
113         else\r
114         {\r
115                 m_nActive++;\r
116         }\r
117 \r
118         HANDLE hsem = NULL;\r
119         LONG lCount = 1;\r
120 \r
121         if (m_nActive == 0)\r
122         {\r
123                 // Note: If there are always writers waiting, then\r
124                 // it's possible that a reader never gets access\r
125                 // (reader starvation)\r
126                 if (m_nWaitingWriters > 0)\r
127                 {\r
128                         m_nActive = -1;\r
129                         m_nWaitingWriters--;\r
130                         hsem = m_hWriters;\r
131                 }\r
132                 else if (m_nWaitingReaders > 0)\r
133                 {\r
134                         m_nActive = m_nWaitingReaders;\r
135                         m_nWaitingReaders = 0;\r
136                         hsem = m_hReaders;\r
137                         lCount = m_nActive;\r
138                 }\r
139                 else\r
140                 {\r
141                         // no threads waiting, nothing to do\r
142                 }\r
143         }\r
144 \r
145         LeaveCriticalSection(&m_cs);\r
146 \r
147         if (hsem != NULL)\r
148         {\r
149                 ReleaseSemaphore(hsem, lCount, NULL);\r
150         }\r
151 }\r
152 \r