1 karl 1.20 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.17 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.15 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.17 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.20 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.2 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.7 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 karl 1.20 //
|
19 kumpf 1.7 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.7 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Day (mdday@us.ibm.com)
31 //
|
32 david.dillard 1.19 // Modified By: David Dillard, VERITAS Software Corp.
33 // (david.dillard@veritas.com)
|
34 mike 1.2 //
35 //%/////////////////////////////////////////////////////////////////////////////
36
37
|
38 david.dillard 1.19 //%// ---- inline implmentations of Windows IPC routines ----
|
39 mike 1.2
40 #ifndef IPCWindows_inline_h
41 #define IPCWindows_inline_h
42
43 //-----------------------------------------------------------------
44 /// Native Windows inline implementation of Mutex class
45 //-----------------------------------------------------------------
46
|
47 david.dillard 1.19 // block until gaining the lock - throw a deadlock
48 // exception if process already holds the lock
|
49 mike 1.2 inline void Mutex::lock(PEGASUS_THREAD_TYPE caller) throw(Deadlock, WaitFailed)
50 {
|
51 david.dillard 1.19 if(_mutex.owner == caller)
52 throw( Deadlock( _mutex.owner ) );
|
53 mike 1.2
|
54 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_mutex.mut, INFINITE);
55 if(errorcode == WAIT_FAILED)
56 throw( WaitFailed( _mutex.owner) );
57 _mutex.owner = caller;
|
58 mike 1.2 }
|
59 david.dillard 1.19
60 // try to gain the lock - lock succeeds immediately if the
|
61 mike 1.2 // mutex is not already locked. throws an exception and returns
|
62 david.dillard 1.19 // immediately if the mutex is currently locked.
|
63 mike 1.2 inline void Mutex::try_lock(PEGASUS_THREAD_TYPE caller) throw(Deadlock, AlreadyLocked, WaitFailed)
64 {
|
65 david.dillard 1.19 if(_mutex.owner == caller)
66 throw( Deadlock( _mutex.owner ) );
|
67 mike 1.2
|
68 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_mutex.mut, 0);
69 if (errorcode == WAIT_TIMEOUT)
70 throw(AlreadyLocked(_mutex.owner));
71 if(errorcode == WAIT_FAILED)
72 throw(WaitFailed(_mutex.owner));
73 _mutex.owner = caller;
|
74 mike 1.2 }
75
76 // wait for milliseconds and throw an exception then return if the wait
77 // expires without gaining the lock. Otherwise return without throwing an
78 // exception.
79
|
80 david.dillard 1.19 inline void Mutex::timed_lock( Uint32 milliseconds , PEGASUS_THREAD_TYPE caller)
81 throw(Deadlock, TimeOut, WaitFailed)
|
82 mike 1.2 {
|
83 david.dillard 1.19 if(_mutex.owner == caller)
84 throw( Deadlock( _mutex.owner ) );
|
85 mike 1.2
|
86 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_mutex.mut, milliseconds);
87 if (errorcode == WAIT_TIMEOUT)
88 throw(TimeOut(_mutex.owner));
89 if(errorcode == WAIT_FAILED)
90 throw(WaitFailed(_mutex.owner));
91 _mutex.owner = caller;
|
92 mike 1.2 }
93
94 // unlock the mutex
95 inline void Mutex::unlock() throw(Permission)
96 {
|
97 david.dillard 1.19 PEGASUS_THREAD_TYPE m_owner = _mutex.owner;
98 _mutex.owner = 0;
99 ReleaseMutex(_mutex.mut);
|
100 mike 1.2 }
101
102
103 //-----------------------------------------------------------------
104 /// Native Windows inline implementation of Semaphore class
105 //-----------------------------------------------------------------
106
107 // block until this semaphore is in a signalled state
|
108 brian.campbell 1.18 // note that windows does not support interrupt
|
109 david.dillard 1.19 inline void Semaphore::wait(Boolean ignoreInterrupt) throw(WaitFailed, WaitInterrupted)
|
110 mike 1.2 {
|
111 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_semaphore.sem, INFINITE);
112 if(errorcode != WAIT_FAILED)
113 _count--;
114 else
115 throw(WaitFailed((PEGASUS_THREAD_TYPE)GetCurrentThreadId()));
|
116 mike 1.2 }
117
|
118 david.dillard 1.19 // wait succeeds immediately if semaphore has a non-zero count,
119 // return immediately and throw and exception if the
120 // count is zero.
|
121 mike 1.2 inline void Semaphore::try_wait(void) throw(WaitFailed)
122 {
|
123 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_semaphore.sem, 0);
124 if(errorcode == WAIT_TIMEOUT || errorcode == WAIT_FAILED)
125 throw(WaitFailed((PEGASUS_THREAD_TYPE)GetCurrentThreadId()));
126 _count--;
|
127 mike 1.2 }
128
129
130 // wait for milliseconds and throw an exception
131 // if wait times out without gaining the semaphore
132 inline void Semaphore::time_wait( Uint32 milliseconds ) throw(TimeOut)
133 {
|
134 david.dillard 1.19 DWORD errorcode = WaitForSingleObject(_semaphore.sem, milliseconds);
135 if (errorcode == WAIT_TIMEOUT || errorcode == WAIT_FAILED)
136 throw(TimeOut((PEGASUS_THREAD_TYPE)GetCurrentThreadId()));
137 _count--;
|
138 mike 1.2 }
139
|
140 david.dillard 1.19 // increment the count of the semaphore
|
141 mike 1.2 inline void Semaphore::signal()
142 {
|
143 david.dillard 1.19 _count++;
144 ReleaseSemaphore(_semaphore.sem, 1, NULL);
|
145 mike 1.2 }
146
147 // return the count of the semaphore
|
148 david.dillard 1.19 inline int Semaphore::count()
|
149 mike 1.2 {
|
150 david.dillard 1.19 return(_count);
|
151 mike 1.2 }
152
153
154 //-----------------------------------------------------------------
155 /// Native Windows inline implementation of AtomicInt class
156 //-----------------------------------------------------------------
157 #if defined(PEGASUS_ATOMIC_INT_NATIVE)
158
|
159 david.dillard 1.19 inline AtomicInt& AtomicInt::operator=(const AtomicInt& original)
|
160 mike 1.2 {
|
161 david.dillard 1.19 InterlockedExchange(&_rep, original._rep);
162 return *this;
|
163 mike 1.2 }
164
165 inline AtomicInt& AtomicInt::operator=(Uint32 val)
166 {
|
167 david.dillard 1.19 InterlockedExchange(&_rep, val);
168 return *this;
|
169 mike 1.2 }
170
|
171 kumpf 1.8 inline Uint32 AtomicInt::value(void) const
|
172 mike 1.2 {
|
173 david.dillard 1.19 return ((Uint32)_rep);
|
174 mike 1.2 }
175
176 inline void AtomicInt::operator++(void) { InterlockedIncrement(&_rep); }
177 inline void AtomicInt::operator--(void) { InterlockedDecrement(&_rep); }
178 inline void AtomicInt::operator++(int) { InterlockedIncrement(&_rep); }
179 inline void AtomicInt::operator--(int) { InterlockedDecrement(&_rep); }
180
|
181 david.dillard 1.19 inline Uint32 AtomicInt::operator+(const AtomicInt& val)
182 {
183 //InterlockedExchangeAdd(&_rep, val._rep);
184 return (_rep + val._rep);
185 }
186
187 inline Uint32 AtomicInt::operator+(Uint32 val)
188 {
189 //InterlockedExchangeAdd(&_rep, val);
190 return (_rep + val);
191 }
192
193 inline Uint32 AtomicInt::operator-(const AtomicInt& val)
194 {
195 //LONG temp_operand, temp_result;
196 //temp_operand = InterlockedExchangeAdd((long *)&(val._rep), 0);
197 //temp_result = InterlockedExchangeAdd(&_rep, 0);
198 //return(temp_result - temp_operand);
199 return (_rep - val._rep);
200 }
201
202 david.dillard 1.19 inline Uint32 AtomicInt::operator-(Uint32 val)
203 {
204 //LONG temp_operand, temp_result;
205 //temp_operand = InterlockedExchangeAdd( (long *)&val, 0);
206 //temp_result = InterlockedExchangeAdd(&_rep, 0);
207 //return(temp_result - temp_operand);
208 return (_rep - val);
209 }
210
211 inline AtomicInt& AtomicInt::operator+=(const AtomicInt& val)
212 {
213 InterlockedExchangeAdd(&_rep, val._rep);
214 return *this;
215 }
216
217 inline AtomicInt& AtomicInt::operator+=(Uint32 val)
218 {
219 InterlockedExchangeAdd(&_rep, val);
220 return *this;
221 }
222
223 david.dillard 1.19 inline AtomicInt& AtomicInt::operator-=(const AtomicInt& val)
|
224 mike 1.2 {
|
225 david.dillard 1.19 LONG temp ;
226 InterlockedExchange(&temp, val._rep);
227 enter_crit(&_crit);
228 _rep -= temp;
229 exit_crit(&_crit);
230
231 return *this;
|
232 mike 1.2 }
233
|
234 david.dillard 1.19 inline AtomicInt& AtomicInt::operator-=(Uint32 val)
235 {
236 LONG temp ;
237 InterlockedExchange(&temp, val);
238 enter_crit(&_crit);
239 _rep -= temp;
240 exit_crit(&_crit);
241
242 return *this;
|
243 mike 1.2 }
244
|
245 kumpf 1.10 inline Boolean AtomicInt::DecAndTestIfZero()
|
246 kumpf 1.9 {
|
247 david.dillard 1.19 return(InterlockedDecrement(&_rep) == 0);
|
248 kumpf 1.9 }
249
|
250 mike 1.2
251 #endif // inline atomic int
252
253 //_________________________________________________________________
254 //
255 /// Native Windows implementation of the conditional semaphore
256 //_________________________________________________________________
257
|
258 david.dillard 1.19 #ifdef PEGASUS_CONDITIONAL_NATIVE
|
259 mike 1.2
260 inline void Condition::signal(PEGASUS_THREAD_TYPE caller)
261 throw(IPCException)
262 {
|
263 david.dillard 1.19 _cond_mutex->lock(caller);
264 try
265 {
266 unlocked_signal(caller);
267 }
268 catch(...)
269 {
270 unlock_object();
271 throw;
272 }
273 _cond_mutex->unlock();
|
274 mike 1.2 }
275
276 inline void Condition::unlocked_signal(PEGASUS_THREAD_TYPE caller)
|
277 david.dillard 1.19 throw(IPCException)
|
278 mike 1.2 {
|
279 david.dillard 1.19 if(_cond_mutex->_mutex.owner != caller)
280 throw Permission((PEGASUS_THREAD_TYPE)caller);
|
281 tony 1.13
|
282 david.dillard 1.19 // Change from PulseEvent to SetEvent, this is part of
|
283 tony 1.13 // fix to avoid deadlock in CIMClient Constructor.
284 //PulseEvent(_condition);
285 SetEvent(_condition);
|
286 mike 1.2 }
287
288 inline void Condition::lock_object(PEGASUS_THREAD_TYPE caller)
|
289 david.dillard 1.19 throw(IPCException)
|
290 mike 1.2 {
|
291 david.dillard 1.19 if(_disallow.value() > 0 )
292 throw ListClosed();
293 _cond_mutex->lock(caller);
|
294 mike 1.2 }
295
296 inline void Condition::try_lock_object(PEGASUS_THREAD_TYPE caller)
|
297 david.dillard 1.19 throw(IPCException)
|
298 mike 1.2 {
|
299 david.dillard 1.19 if(_disallow.value() > 0 )
300 throw ListClosed();
301 _cond_mutex->try_lock(caller);
|
302 mike 1.2 }
303
304 inline void Condition::wait_lock_object(PEGASUS_THREAD_TYPE caller, int milliseconds)
|
305 david.dillard 1.19 throw(IPCException)
|
306 mike 1.2 {
|
307 david.dillard 1.19 if(_disallow.value() > 0)
308 throw ListClosed();
309 _cond_mutex->timed_lock(milliseconds, caller);
310 if( _disallow.value() > 0 )
311 {
312 _cond_mutex->unlock();
313 throw ListClosed();
314 }
|
315 mike 1.2 }
316
317 inline void Condition::unlock_object(void)
318 {
|
319 david.dillard 1.19 _cond_mutex->unlock();
|
320 mike 1.2 }
321
322 inline void Condition::unlocked_wait(PEGASUS_THREAD_TYPE caller)
323 {
|
324 david.dillard 1.19 unlocked_timed_wait(-1, caller);
|
325 mike 1.2 }
326
327 inline void Condition::unlocked_timed_wait(int milliseconds, PEGASUS_THREAD_TYPE caller)
328 {
|
329 david.dillard 1.19 if(_disallow.value() > 0)
330 {
331 _cond_mutex->unlock();
332 throw ListClosed();
333 }
334
335 if(_cond_mutex->_mutex.owner != caller)
336 throw Permission((PEGASUS_THREAD_TYPE)caller);
337 if(milliseconds == -1)
338 milliseconds = INFINITE;
|
339 tony 1.13
|
340 david.dillard 1.19 // Change from PulseEvent to SetEvent, this is part of
341 // fix to avoid deadlock in CIMClient Constructor
|
342 tony 1.13 // Change added next line since SignalObjectAndWait
343 // releases the mutex
344 _cond_mutex->_mutex.owner = 0;
345
|
346 david.dillard 1.19 DWORD retcode = SignalObjectAndWait(_cond_mutex->_mutex.mut, _condition,
347 milliseconds, false);
348 if(retcode == WAIT_TIMEOUT)
349 throw TimeOut(pegasus_thread_self());
350 _cond_mutex->lock(caller);
|
351 mike 1.2 }
352
353
|
354 david.dillard 1.19 #endif // inline native conditional
|
355 mike 1.2
356 #endif // IPCWindows_inline_h
|