(file) Return to Mutex.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 martin 1.16 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.17 //
  3 martin 1.16 // Licensed to The Open Group (TOG) under one or more contributor license
  4             // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5             // this work for additional information regarding copyright ownership.
  6             // Each contributor licenses this file to you under the OpenPegasus Open
  7             // Source License; you may not use this file except in compliance with the
  8             // License.
  9 martin 1.17 //
 10 martin 1.16 // Permission is hereby granted, free of charge, to any person obtaining a
 11             // copy of this software and associated documentation files (the "Software"),
 12             // to deal in the Software without restriction, including without limitation
 13             // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14             // and/or sell copies of the Software, and to permit persons to whom the
 15             // Software is furnished to do so, subject to the following conditions:
 16 martin 1.17 //
 17 martin 1.16 // The above copyright notice and this permission notice shall be included
 18             // in all copies or substantial portions of the Software.
 19 martin 1.17 //
 20 martin 1.16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.17 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23             // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24             // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25             // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26             // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.17 //
 28 martin 1.16 //////////////////////////////////////////////////////////////////////////
 29 mike   1.2  //
 30             //%/////////////////////////////////////////////////////////////////////////////
 31             
 32             #include "Mutex.h"
 33 mike   1.4  #include "Time.h"
 34             #include "PegasusAssert.h"
 35             #include "Once.h"
 36 kumpf  1.14 #include "Exception.h"
 37             #include "System.h"
 38             
 39             #define MUTEX_LOCK_FAILED_KEY "Common.InternalException.MUTEX_LOCK_FAILED"
 40             #define MUTEX_LOCK_FAILED_MSG "Failed to acquire mutex lock: $0"
 41 mike   1.2  
 42             PEGASUS_NAMESPACE_BEGIN
 43             
 44 mike   1.4  //==============================================================================
 45             //
 46             // PEGASUS_HAVE_PTHREADS
 47             //
 48             //==============================================================================
 49             
 50             #if defined(PEGASUS_HAVE_PTHREADS)
 51             
 52             static Once _once = PEGASUS_ONCE_INITIALIZER;
 53             static pthread_mutexattr_t _attr;
 54             
 55             static void _init_attr()
 56             {
 57                 pthread_mutexattr_init(&_attr);
 58                 pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
 59             }
 60             
 61             Mutex::Mutex()
 62             {
 63                 once(&_once, _init_attr);
 64                 pthread_mutex_init(&_rep.mutex, &_attr);
 65 mike   1.4  #if defined(PEGASUS_DEBUG)
 66                 _rep.count = 0;
 67             #endif
 68             }
 69             
 70 mike   1.6  Mutex::Mutex(RecursiveTag)
 71             {
 72                 once(&_once, _init_attr);
 73                 pthread_mutex_init(&_rep.mutex, &_attr);
 74             #if defined(PEGASUS_DEBUG)
 75                 _rep.count = 0;
 76             #endif
 77             }
 78             
 79             Mutex::Mutex(NonRecursiveTag)
 80             {
 81                 pthread_mutex_init(&_rep.mutex, NULL);
 82             #if defined(PEGASUS_DEBUG)
 83                 _rep.count = 0;
 84             #endif
 85             }
 86             
 87 mike   1.4  Mutex::~Mutex()
 88             {
 89                 PEGASUS_DEBUG_ASSERT(_magic);
 90                 pthread_mutex_destroy(&_rep.mutex);
 91             }
 92             
 93             void Mutex::lock()
 94             {
 95                 PEGASUS_DEBUG_ASSERT(_magic);
 96             
 97 kumpf  1.14     int r = pthread_mutex_lock(&_rep.mutex);
 98             
 99                 if (r == 0)
100 mike   1.4      {
101             #if defined(PEGASUS_DEBUG)
102 kumpf  1.14         _rep.count++;
103 mike   1.4  #endif
104 kumpf  1.14     }
105                 else
106                 {
107                     if (r != -1)
108                     {
109                         // Special behavior for Single UNIX Specification, Version 3
110                         errno = r;
111                     }
112 mike   1.4  
113 kumpf  1.14         throw Exception(MessageLoaderParms(
114                         MUTEX_LOCK_FAILED_KEY,
115                         MUTEX_LOCK_FAILED_MSG,
116                         PEGASUS_SYSTEM_ERRORMSG_NLS));
117 mike   1.4      }
118             }
119             
120 kumpf  1.12 Boolean Mutex::try_lock()
121 mike   1.4  {
122                 PEGASUS_DEBUG_ASSERT(_magic);
123             
124 marek  1.5      int r = pthread_mutex_trylock(&_rep.mutex);
125 kumpf  1.12 
126                 if (r == 0)
127 mike   1.4      {
128             #if defined(PEGASUS_DEBUG)
129 kumpf  1.12         _rep.count++;
130 mike   1.4  #endif
131 kumpf  1.12         return true;
132                 }
133 mike   1.4  
134 kumpf  1.14     if (r != -1)
135                 {
136                     // Special behavior for Single UNIX Specification, Version 3
137                     errno = r;
138                 }
139             
140                 if (errno == EBUSY)
141 kumpf  1.12     {
142                     return false;
143                 }
144 mike   1.4  
145 kumpf  1.14     throw Exception(MessageLoaderParms(
146                     MUTEX_LOCK_FAILED_KEY,
147                     MUTEX_LOCK_FAILED_MSG,
148                     PEGASUS_SYSTEM_ERRORMSG_NLS));
149 mike   1.4  }
150             
151 kumpf  1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
152 mike   1.4  {
153                 struct timeval now;
154                 struct timeval finish;
155                 struct timeval remaining;
156                 {
157                     Uint32 usec;
158                     gettimeofday(&finish, NULL);
159                     finish.tv_sec += (milliseconds / 1000 );
160                     milliseconds %= 1000;
161                     usec = finish.tv_usec + ( milliseconds * 1000 );
162                     finish.tv_sec += (usec / 1000000);
163                     finish.tv_usec = usec % 1000000;
164                 }
165             
166 kumpf  1.14     while (!try_lock())
167 mike   1.4      {
168 kumpf  1.14         gettimeofday(&now, NULL);
169 kumpf  1.11 
170 kumpf  1.14         if (Time::subtract(&remaining, &finish, &now))
171 kumpf  1.11         {
172 kumpf  1.14             return false;
173 kumpf  1.11         }
174 mike   1.4  
175 kumpf  1.14         Threads::yield();
176 mike   1.4      }
177 kumpf  1.11 
178                 return true;
179 mike   1.4  }
180             
181             void Mutex::unlock()
182             {
183                 PEGASUS_DEBUG_ASSERT(_magic);
184                 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
185             
186             #if defined(PEGASUS_DEBUG)
187                 _rep.count--;
188             #endif
189             
190 kumpf  1.13     // All documented error codes represent coding errors.
191 karl   1.18.6.1     PEGASUS_FCT_EXECUTE_AND_ASSERT(0, pthread_mutex_unlock(&_rep.mutex));
192 mike   1.4      }
193                 
194 thilo.boehm 1.15     #if defined(PEGASUS_OS_LINUX)
195 kumpf       1.8      void Mutex::reinitialize()
196                      {
197                          pthread_mutex_init(&_rep.mutex, &_attr);
198                      #if defined(PEGASUS_DEBUG)
199                          _rep.count = 0;
200                      #endif
201                      }
202                      #endif
203                      
204 mike        1.4      #endif /* PEGASUS_HAVE_PTHREADS */
205                      
206                      //==============================================================================
207                      //
208                      // PEGASUS_HAVE_WINDOWS_THREADS
209                      //
210                      //==============================================================================
211                      
212                      #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
213                      
214 mike        1.7      static inline void _initialize(MutexRep& rep)
215                      {
216                          rep.handle = CreateMutex(NULL, FALSE, NULL);
217 kavita.gupta 1.18         if (rep.handle == NULL)
218                           {
219                               throw Exception(MessageLoaderParms(
220                                   "Common.InternalException.CREATE_MUTEX_FAILED",
221                                   "CreateMutex failed : $0",
222                                   PEGASUS_SYSTEM_ERRORMSG_NLS));
223                           }
224 mike         1.7          rep.count = 0;
225                       }
226                       
227 mike         1.4      Mutex::Mutex()
228                       {
229 mike         1.7          _initialize(_rep);
230                       }
231                       
232 mike         1.6      Mutex::Mutex(RecursiveTag)
233                       {
234 mike         1.7          _initialize(_rep);
235 mike         1.6      }
236                       
237                       Mutex::Mutex(NonRecursiveTag)
238                       {
239 mike         1.7          _initialize(_rep);
240 mike         1.4      }
241                       
242                       Mutex::~Mutex()
243                       {
244                           PEGASUS_DEBUG_ASSERT(_magic);
245                       
246                           WaitForSingleObject(_rep.handle, INFINITE);
247                           CloseHandle(_rep.handle);
248                       }
249                       
250                       void Mutex::lock()
251                       {
252                           PEGASUS_DEBUG_ASSERT(_magic);
253                       
254                           DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
255                       
256                           if (rc == WAIT_FAILED)
257 kumpf        1.14         {
258                               throw Exception(MessageLoaderParms(
259                                   MUTEX_LOCK_FAILED_KEY,
260                                   MUTEX_LOCK_FAILED_MSG,
261                                   PEGASUS_SYSTEM_ERRORMSG_NLS));
262                           }
263 mike         1.4      
264                           _rep.count++;
265                       }
266                       
267 kumpf        1.12     Boolean Mutex::try_lock()
268 mike         1.4      {
269                           PEGASUS_DEBUG_ASSERT(_magic);
270                       
271                           DWORD rc = WaitForSingleObject(_rep.handle, 0);
272                       
273                           if (rc == WAIT_TIMEOUT)
274 kumpf        1.12         {
275                               return false;
276                           }
277 mike         1.4      
278                           if (rc == WAIT_FAILED)
279 kumpf        1.12         {
280 kumpf        1.14             throw Exception(MessageLoaderParms(
281                                   MUTEX_LOCK_FAILED_KEY,
282                                   MUTEX_LOCK_FAILED_MSG,
283                                   PEGASUS_SYSTEM_ERRORMSG_NLS));
284 kumpf        1.12         }
285 mike         1.4      
286                           _rep.count++;
287 kumpf        1.12         return true;
288 mike         1.4      }
289                       
290 kumpf        1.11     Boolean Mutex::timed_lock(Uint32 milliseconds)
291 mike         1.4      {
292                           PEGASUS_DEBUG_ASSERT(_magic);
293                       
294                           DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
295                       
296                           if (rc == WAIT_TIMEOUT)
297 kumpf        1.11             return false;
298 mike         1.4      
299                           if (rc == WAIT_FAILED)
300 kumpf        1.14         {
301                               throw Exception(MessageLoaderParms(
302                                   MUTEX_LOCK_FAILED_KEY,
303                                   MUTEX_LOCK_FAILED_MSG,
304                                   PEGASUS_SYSTEM_ERRORMSG_NLS));
305                           }
306 mike         1.4      
307                           _rep.count++;
308 kumpf        1.11         return true;
309 mike         1.4      }
310                       
311                       void Mutex::unlock()
312                       {
313                           PEGASUS_DEBUG_ASSERT(_magic);
314                           PEGASUS_DEBUG_ASSERT(_rep.count > 0);
315                       
316                           _rep.count--;
317                           ReleaseMutex(_rep.handle);
318                       }
319                       
320                       #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
321                       
322 mike         1.2      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2