1 karl 1.3 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
3 // 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 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.3 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.3 //
|
21 mike 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
|
32 mike 1.3.14.5 // Author: Mike Brasher (m.brasher@inovadevelopment.com)
|
33 mike 1.3.14.1 //
|
34 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
35
36 #include "Mutex.h"
|
37 mike 1.3.14.1 #include "Time.h"
38 #include "PegasusAssert.h"
|
39 mike 1.3.14.6 #include "Once.h"
|
40 mike 1.2
41 PEGASUS_NAMESPACE_BEGIN
42
|
43 mike 1.3.14.1 //==============================================================================
44 //
45 // PEGASUS_HAVE_PTHREADS
46 //
47 //==============================================================================
48
49 #if defined(PEGASUS_HAVE_PTHREADS)
50
|
51 mike 1.3.14.6 static Once _once = PEGASUS_ONCE_INITIALIZER;
52 static pthread_mutexattr_t _attr;
|
53 mike 1.3.14.1
|
54 mike 1.3.14.6 static void _init_attr()
|
55 mike 1.3.14.1 {
|
56 mike 1.3.14.6 pthread_mutexattr_init(&_attr);
57 pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
|
58 mike 1.3.14.1 }
59
|
60 mike 1.3.14.6 Mutex::Mutex()
|
61 mike 1.3.14.1 {
|
62 mike 1.3.14.6 once(&_once, _init_attr);
63 pthread_mutex_init(&_rep.mutex, &_attr);
|
64 mike 1.3.14.9 _rep.count = 0;
|
65 mike 1.3.14.1 }
66
|
67 mike 1.3.14.7 Mutex::~Mutex()
68 {
69 PEGASUS_DEBUG_ASSERT(_magic);
70 pthread_mutex_destroy(&_rep.mutex);
|
71 mike 1.3.14.9 _rep.count = -1;
|
72 mike 1.3.14.7 }
73
|
74 mike 1.3.14.8 void Mutex::lock()
75 {
76 PEGASUS_DEBUG_ASSERT(_magic);
77
78 switch (pthread_mutex_lock(&_rep.mutex))
79 {
80 case 0:
|
81 mike 1.3.14.9 _rep.count++;
|
82 mike 1.3.14.8 break;
83
84 case EDEADLK:
85 throw Deadlock(ThreadType());
86
87 default:
88 throw WaitFailed(ThreadType());
89 }
90 }
91
|
92 mike 1.3.14.5 void Mutex::try_lock()
|
93 mike 1.3.14.1 {
94 PEGASUS_DEBUG_ASSERT(_magic);
95
96 switch (pthread_mutex_trylock(&_rep.mutex))
97 {
98 case 0:
|
99 mike 1.3.14.9 _rep.count++;
|
100 mike 1.3.14.1 break;
101
102 case EBUSY:
|
103 mike 1.3.14.5 throw AlreadyLocked(ThreadType());
|
104 mike 1.3.14.1
105 case EDEADLK:
|
106 mike 1.3.14.5 throw Deadlock(ThreadType());
|
107 mike 1.3.14.1
108 default:
|
109 mike 1.3.14.5 throw WaitFailed(ThreadType());
|
110 mike 1.3.14.1 }
111 }
112
|
113 mike 1.3.14.5 void Mutex::timed_lock(Uint32 milliseconds)
|
114 mike 1.3.14.1 {
115 PEGASUS_DEBUG_ASSERT(_magic);
116
117 struct timeval now;
118 struct timeval finish;
119 struct timeval remaining;
120 {
121 Uint32 usec;
122 gettimeofday(&finish, NULL);
123 finish.tv_sec += (milliseconds / 1000 );
124 milliseconds %= 1000;
125 usec = finish.tv_usec + ( milliseconds * 1000 );
126 finish.tv_sec += (usec / 1000000);
127 finish.tv_usec = usec % 1000000;
128 }
129
130 for (;;)
131 {
132 switch (pthread_mutex_trylock(&_rep.mutex))
133 {
134 case 0:
|
135 mike 1.3.14.9 _rep.count++;
|
136 mike 1.3.14.1 return;
137
138 case EBUSY:
139 {
140 gettimeofday(&now, NULL);
141
142 if (Time::subtract(&remaining, &finish, &now))
143 throw TimeOut(Threads::self());
144
145 Threads::yield();
146 break;
147 }
148
149 case EDEADLK:
150 throw Deadlock(Threads::self());
151
152 default:
153 throw WaitFailed(Threads::self());
154 }
155 }
156 }
157 mike 1.3.14.1
|
158 mike 1.3.14.8 void Mutex::unlock()
159 {
160 PEGASUS_DEBUG_ASSERT(_magic);
|
161 mike 1.3.14.9 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
|
162 mike 1.3.14.8
163 if (pthread_mutex_unlock(&_rep.mutex) != 0)
164 throw Permission(ThreadType());
|
165 mike 1.3.14.9
166 _rep.count--;
|
167 mike 1.3.14.8 }
168
|
169 mike 1.3.14.1 #endif /* PEGASUS_HAVE_PTHREADS */
170
171 //==============================================================================
172 //
173 // PEGASUS_HAVE_WINDOWS_THREADS
174 //
175 //==============================================================================
176
177 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
178
179 Mutex::Mutex()
180 {
181 _rep.handle = CreateMutex(NULL, FALSE, NULL);
|
182 mike 1.3.14.5 Threads::clear(ThreadType());
|
183 mike 1.3.14.8 _rep.count = 0;
|
184 mike 1.3.14.1 }
185
186 Mutex::~Mutex()
187 {
188 PEGASUS_DEBUG_ASSERT(_magic);
189
190 WaitForSingleObject(_rep.handle, INFINITE);
191 CloseHandle(_rep.handle);
192 }
193
|
194 mike 1.3.14.8 void Mutex::lock()
195 {
196 PEGASUS_DEBUG_ASSERT(_magic);
197
198 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
199
200 if (rc == WAIT_FAILED)
201 throw WaitFailed(ThreadType());
202
203 _rep.count++;
204 }
205
|
206 mike 1.3.14.5 void Mutex::try_lock()
|
207 mike 1.3.14.1 {
208 PEGASUS_DEBUG_ASSERT(_magic);
209
210 DWORD rc = WaitForSingleObject(_rep.handle, 0);
211
212 if (rc == WAIT_TIMEOUT)
|
213 mike 1.3.14.5 throw AlreadyLocked(ThreadType());
|
214 mike 1.3.14.1
215 if (rc == WAIT_FAILED)
|
216 mike 1.3.14.5 throw WaitFailed(ThreadType());
|
217 mike 1.3.14.8
218 _rep.count++;
|
219 mike 1.3.14.1 }
220
|
221 mike 1.3.14.5 void Mutex::timed_lock(Uint32 milliseconds)
|
222 mike 1.3.14.1 {
223 PEGASUS_DEBUG_ASSERT(_magic);
224
225 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
226
227 if (rc == WAIT_TIMEOUT)
|
228 mike 1.3.14.5 throw TimeOut(ThreadType());
|
229 mike 1.3.14.1
230 if (rc == WAIT_FAILED)
|
231 mike 1.3.14.5 throw WaitFailed(ThreadType());
|
232 mike 1.3.14.8
233 _rep.count++;
234 }
235
236 void Mutex::unlock()
237 {
238 PEGASUS_DEBUG_ASSERT(_magic);
239
240 Threads::clear(ThreadType());
241 _rep.count--;
242 ReleaseMutex(_rep.handle);
|
243 mike 1.3.14.1 }
244
245 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
246
|
247 mike 1.2 PEGASUS_NAMESPACE_END
|