(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     int rc = pthread_mutex_unlock(&_rep.mutex);
191                 // All documented error codes represent coding errors.
192                 PEGASUS_ASSERT(rc == 0);
193 mike   1.4  }
194             
195 thilo.boehm 1.15 #if defined(PEGASUS_OS_LINUX)
196 kumpf       1.8  void Mutex::reinitialize()
197                  {
198                      pthread_mutex_init(&_rep.mutex, &_attr);
199                  #if defined(PEGASUS_DEBUG)
200                      _rep.count = 0;
201                  #endif
202                  }
203                  #endif
204                  
205 mike        1.4  #endif /* PEGASUS_HAVE_PTHREADS */
206                  
207                  //==============================================================================
208                  //
209                  // PEGASUS_HAVE_WINDOWS_THREADS
210                  //
211                  //==============================================================================
212                  
213                  #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
214                  
215 mike        1.7  static inline void _initialize(MutexRep& rep)
216                  {
217                      rep.handle = CreateMutex(NULL, FALSE, NULL);
218 kavita.gupta 1.18     if (rep.handle == NULL)
219                       {
220                           throw Exception(MessageLoaderParms(
221                               "Common.InternalException.CREATE_MUTEX_FAILED",
222                               "CreateMutex failed : $0",
223                               PEGASUS_SYSTEM_ERRORMSG_NLS));
224                       }
225 mike         1.7      rep.count = 0;
226                   }
227                   
228 mike         1.4  Mutex::Mutex()
229                   {
230 mike         1.7      _initialize(_rep);
231                   }
232                   
233 mike         1.6  Mutex::Mutex(RecursiveTag)
234                   {
235 mike         1.7      _initialize(_rep);
236 mike         1.6  }
237                   
238                   Mutex::Mutex(NonRecursiveTag)
239                   {
240 mike         1.7      _initialize(_rep);
241 mike         1.4  }
242                   
243                   Mutex::~Mutex()
244                   {
245                       PEGASUS_DEBUG_ASSERT(_magic);
246                   
247                       WaitForSingleObject(_rep.handle, INFINITE);
248                       CloseHandle(_rep.handle);
249                   }
250                   
251                   void Mutex::lock()
252                   {
253                       PEGASUS_DEBUG_ASSERT(_magic);
254                   
255                       DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
256                   
257                       if (rc == WAIT_FAILED)
258 kumpf        1.14     {
259                           throw Exception(MessageLoaderParms(
260                               MUTEX_LOCK_FAILED_KEY,
261                               MUTEX_LOCK_FAILED_MSG,
262                               PEGASUS_SYSTEM_ERRORMSG_NLS));
263                       }
264 mike         1.4  
265                       _rep.count++;
266                   }
267                   
268 kumpf        1.12 Boolean Mutex::try_lock()
269 mike         1.4  {
270                       PEGASUS_DEBUG_ASSERT(_magic);
271                   
272                       DWORD rc = WaitForSingleObject(_rep.handle, 0);
273                   
274                       if (rc == WAIT_TIMEOUT)
275 kumpf        1.12     {
276                           return false;
277                       }
278 mike         1.4  
279                       if (rc == WAIT_FAILED)
280 kumpf        1.12     {
281 kumpf        1.14         throw Exception(MessageLoaderParms(
282                               MUTEX_LOCK_FAILED_KEY,
283                               MUTEX_LOCK_FAILED_MSG,
284                               PEGASUS_SYSTEM_ERRORMSG_NLS));
285 kumpf        1.12     }
286 mike         1.4  
287                       _rep.count++;
288 kumpf        1.12     return true;
289 mike         1.4  }
290                   
291 kumpf        1.11 Boolean Mutex::timed_lock(Uint32 milliseconds)
292 mike         1.4  {
293                       PEGASUS_DEBUG_ASSERT(_magic);
294                   
295                       DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
296                   
297                       if (rc == WAIT_TIMEOUT)
298 kumpf        1.11         return false;
299 mike         1.4  
300                       if (rc == WAIT_FAILED)
301 kumpf        1.14     {
302                           throw Exception(MessageLoaderParms(
303                               MUTEX_LOCK_FAILED_KEY,
304                               MUTEX_LOCK_FAILED_MSG,
305                               PEGASUS_SYSTEM_ERRORMSG_NLS));
306                       }
307 mike         1.4  
308                       _rep.count++;
309 kumpf        1.11     return true;
310 mike         1.4  }
311                   
312                   void Mutex::unlock()
313                   {
314                       PEGASUS_DEBUG_ASSERT(_magic);
315                       PEGASUS_DEBUG_ASSERT(_rep.count > 0);
316                   
317                       _rep.count--;
318                       ReleaseMutex(_rep.handle);
319                   }
320                   
321                   #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
322                   
323 mike         1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2