blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #include "blocxx/BLOCXX_config.h" 00040 #include "blocxx/MutexImpl.hpp" 00041 #include <cerrno> 00042 #include <cassert> 00043 00044 namespace BLOCXX_NAMESPACE 00045 { 00046 00047 namespace MutexImpl 00048 { 00049 00050 #if defined (BLOCXX_USE_PTHREAD) 00051 00052 #if !defined (BLOCXX_NCR) 00053 00059 int 00060 createMutex(Mutex_t& handle) 00061 { 00062 pthread_mutexattr_t attr; 00063 int res = pthread_mutexattr_init(&attr); 00064 assert(res == 0); 00065 if (res != 0) 00066 { 00067 return -1; 00068 } 00069 00070 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00071 res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 00072 assert(res == 0); 00073 if (res != 0) 00074 { 00075 pthread_mutexattr_destroy(&attr); 00076 return -1; 00077 } 00078 #endif 00079 00080 res = pthread_mutex_init(&handle.mutex, &attr); 00081 pthread_mutexattr_destroy(&attr); 00082 if (res != 0) 00083 { 00084 return -1; 00085 } 00086 00087 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00088 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT); 00089 if (res != 0) 00090 { 00091 pthread_mutex_destroy(&handle.mutex); 00092 return -1; 00093 } 00094 00095 handle.valid_id = false; 00096 handle.count = 0; 00097 #endif 00098 return 0; 00099 } 00100 00101 #else //#if !defined (BLOCXX_NCR) 00102 00103 int 00104 createMutex(Mutex_t& handle) 00105 { 00106 pthread_mutexattr_t attr; 00107 int res = pthread_mutexattr_create(&attr); 00108 assert(res == 0); 00109 if (res != 0) 00110 { 00111 return -1; 00112 } 00113 00114 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00115 res = pthread_mutexattr_setkind_np(&attr, MUTEX_RECURSIVE_NP); 00116 assert(res == 0); 00117 if (res != 0) 00118 { 00119 pthread_mutexattr_delete(&attr); 00120 return -1; 00121 } 00122 #endif 00123 00124 res = pthread_mutex_init(&handle.mutex, attr); 00125 00126 pthread_mutexattr_delete(&attr); 00127 if (res != 0) 00128 { 00129 return -1; 00130 } 00131 00132 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00133 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT); 00134 if (res != 0) 00135 { 00136 pthread_mutex_destroy(&handle.mutex); 00137 return -1; 00138 } 00139 00140 handle.valid_id = false; 00141 handle.count = 0; 00142 #endif 00143 return 0; 00144 } 00145 00146 #endif //#ifndef BLOCXX_NCR 00147 00157 int 00158 destroyMutex(Mutex_t& handle) 00159 { 00160 switch (pthread_mutex_destroy(&handle.mutex)) 00161 { 00162 case 0: 00163 break; 00164 case EBUSY: 00165 return -1; 00166 break; 00167 default: 00168 return -2; 00169 } 00170 int res = 0; 00171 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00172 res = pthread_cond_destroy(&handle.unlocked); 00173 assert(res == 0); 00174 #endif 00175 return res; 00176 } 00177 00186 int 00187 acquireMutex(Mutex_t& handle) 00188 { 00189 int res = pthread_mutex_lock(&handle.mutex); 00190 assert(res == 0); 00191 00192 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00193 pthread_t tid = pthread_self(); 00194 if (handle.valid_id && pthread_equal(handle.thread_id, tid)) 00195 { 00196 ++handle.count; 00197 } 00198 else 00199 { 00200 while (handle.valid_id) 00201 { 00202 res = pthread_cond_wait(&handle.unlocked, &handle.mutex); 00203 assert(res == 0 || res == EINTR); 00204 if (res == EINTR) 00205 { 00206 try 00207 { 00208 Thread::testCancel(); 00209 } 00210 catch (...) 00211 { 00212 pthread_mutex_unlock(&handle.mutex); 00213 throw; 00214 } 00215 } 00216 } 00217 00218 handle.thread_id = tid; 00219 handle.valid_id = true; 00220 handle.count = 1; 00221 } 00222 00223 res = pthread_mutex_unlock(&handle.mutex); 00224 assert(res == 0); 00225 #endif 00226 return res; 00227 } 00228 00235 int 00236 releaseMutex(Mutex_t& handle) 00237 { 00238 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00239 int res = pthread_mutex_unlock(&handle.mutex); 00240 assert(res == 0); 00241 return res; 00242 #else 00243 int res = 0; 00244 res = pthread_mutex_lock(&handle.mutex); 00245 assert(res == 0); 00246 00247 pthread_t tid = pthread_self(); 00248 if (handle.valid_id && !pthread_equal(handle.thread_id, tid)) 00249 { 00250 res = pthread_mutex_unlock(&handle.mutex); 00251 assert(res == 0); 00252 return -1; 00253 } 00254 00255 if (--handle.count == 0) 00256 { 00257 assert(handle.valid_id); 00258 handle.valid_id = false; 00259 00260 res = pthread_cond_signal(&handle.unlocked); 00261 assert(res == 0); 00262 } 00263 00264 res = pthread_mutex_unlock(&handle.mutex); 00265 assert(res == 0); 00266 return res; 00267 #endif //#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE) 00268 } 00269 00270 #endif //#if defined (BLOCXX_USE_PTHREAD) 00271 00272 #if defined(BLOCXX_WIN32) 00273 00274 int 00275 createMutex(Mutex_t& handle) 00276 { 00277 handle = new CRITICAL_SECTION; 00278 assert(handle); 00279 InitializeCriticalSection(handle); 00280 return 0; 00281 } 00282 00283 int 00284 destroyMutex(Mutex_t& handle) 00285 { 00286 if(handle) 00287 { 00288 DeleteCriticalSection(handle); 00289 delete handle; 00290 handle = 0; 00291 } 00292 return 0; 00293 } 00294 00295 int 00296 acquireMutex(Mutex_t& handle) 00297 { 00298 EnterCriticalSection(handle); 00299 return 0; 00300 } 00301 00302 int 00303 releaseMutex(Mutex_t& handle) 00304 { 00305 LeaveCriticalSection(handle); 00306 return 0; 00307 } 00308 00309 #endif //#if defined(BLOCXX_WIN32) 00310 00311 } // end namespace MutexImpl 00312 } // end namespace BLOCXX_NAMESPACE 00313