Merge branch 'selection-navigation'
[TortoiseGit.git] / src / AsyncFramework / WaitableEvent.cpp
blob4a0dbdc4ecc65ee19901557d95d12459714195d5
1 /***************************************************************************
2 * Copyright (C) 2009 by Stefan Fuhrmann *
3 * stefanfuhrmann@alice-dsl.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "stdafx.h"
22 #include "WaitableEvent.h"
23 #include "CriticalSection.h"
25 namespace async
28 // recycler for OS constructs
30 namespace
32 class CWaitableEventPool
34 private:
36 // multi-threading sync.
38 CCriticalSection mutex;
40 // allocated, currently usused handles
42 std::vector<HANDLE> handles;
44 // flag indicating that this instance has not been destroyed, yet
46 volatile LONG alive;
48 // construction / destruction:
49 // free all handles upon destruction at latest
51 CWaitableEventPool();
52 ~CWaitableEventPool();
54 public:
56 // Meyer's singleton
58 static CWaitableEventPool* GetInstance();
60 // recycling interface:
61 // alloc at request
63 HANDLE Alloc();
64 void AutoAlloc (HANDLE& handle);
65 void Release (HANDLE event);
66 void Clear();
69 // construction / destruction:
71 CWaitableEventPool::CWaitableEventPool()
72 : alive (TRUE)
76 CWaitableEventPool::~CWaitableEventPool()
78 Clear();
79 InterlockedExchange (&alive, FALSE);
82 // Meyer's singleton
84 CWaitableEventPool* CWaitableEventPool::GetInstance()
86 static CWaitableEventPool instance;
87 return &instance;
90 // recycling interface:
91 // alloc at request
93 HANDLE CWaitableEventPool::Alloc()
95 if (InterlockedCompareExchange (&alive, TRUE, TRUE))
97 CCriticalSectionLock lock (mutex);
98 if (!handles.empty())
100 HANDLE result = handles.back();
101 handles.pop_back();
102 return result;
106 return CreateEvent (NULL, TRUE, FALSE, NULL);
109 void CWaitableEventPool::AutoAlloc (HANDLE& handle)
111 if (handle != NULL)
112 return;
114 if (InterlockedCompareExchange (&alive, TRUE, TRUE))
116 CCriticalSectionLock lock (mutex);
117 if (!handles.empty())
119 handle = handles.back();
120 handles.pop_back();
121 return;
125 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
128 void CWaitableEventPool::Release (HANDLE event)
130 ResetEvent (event);
131 if (InterlockedCompareExchange (&alive, TRUE, TRUE))
133 CCriticalSectionLock lock (mutex);
134 handles.push_back (event);
136 else
138 CloseHandle (event);
142 void CWaitableEventPool::Clear()
144 CCriticalSectionLock lock (mutex);
146 while (!handles.empty())
147 CloseHandle (Alloc());
151 // construction / destruction: manage event handle
153 COneShotEvent::COneShotEvent()
154 : event (NULL)
155 , state (FALSE)
159 COneShotEvent::~COneShotEvent()
161 if (event != NULL)
162 CWaitableEventPool::GetInstance()->Release (event);
165 // eventing interface
167 void COneShotEvent::Set()
169 if (InterlockedExchange (&state, TRUE) == FALSE)
170 if (event != NULL)
171 SetEvent (event);
174 bool COneShotEvent::Test() const
176 return state == TRUE;
179 void COneShotEvent::WaitFor()
181 if (state == FALSE)
183 CWaitableEventPool::GetInstance()->AutoAlloc (event);
184 if (state == FALSE)
185 WaitForSingleObject (event, INFINITE);
189 bool COneShotEvent::WaitForEndOrTimeout(DWORD milliSeconds)
191 if (state == FALSE)
193 CWaitableEventPool::GetInstance()->AutoAlloc (event);
194 return WaitForSingleObject (event, milliSeconds) == WAIT_OBJECT_0;
197 return true;
200 // construction / destruction: manage event handle
202 CWaitableEvent::CWaitableEvent()
203 : event (CWaitableEventPool::GetInstance()->Alloc())
207 CWaitableEvent::~CWaitableEvent()
209 CWaitableEventPool::GetInstance()->Release (event);
212 // eventing interface
214 void CWaitableEvent::Set()
216 SetEvent (event);
219 void CWaitableEvent::Reset()
221 ResetEvent (event);
224 bool CWaitableEvent::Test() const
226 return WaitForSingleObject (event, 0) == WAIT_OBJECT_0;
229 void CWaitableEvent::WaitFor()
231 WaitForSingleObject (event, INFINITE);
234 bool CWaitableEvent::WaitForEndOrTimeout(DWORD milliSeconds)
236 return WaitForSingleObject (event, milliSeconds) == WAIT_OBJECT_0;