recursive_mutex.h

00001 /*
00002     Copyright 2005-2010 Intel Corporation.  All Rights Reserved.
00003 
00004     The source code contained or described herein and all documents related
00005     to the source code ("Material") are owned by Intel Corporation or its
00006     suppliers or licensors.  Title to the Material remains with Intel
00007     Corporation or its suppliers and licensors.  The Material is protected
00008     by worldwide copyright laws and treaty provisions.  No part of the
00009     Material may be used, copied, reproduced, modified, published, uploaded,
00010     posted, transmitted, distributed, or disclosed in any way without
00011     Intel's prior express written permission.
00012 
00013     No license under any patent, copyright, trade secret or other
00014     intellectual property right is granted to or conferred upon you by
00015     disclosure or delivery of the Materials, either expressly, by
00016     implication, inducement, estoppel or otherwise.  Any license under such
00017     intellectual property rights must be express and approved by Intel in
00018     writing.
00019 */
00020 
00021 #ifndef __TBB_recursive_mutex_H
00022 #define __TBB_recursive_mutex_H
00023 
00024 #if _WIN32||_WIN64
00025     #include <windows.h>
00026     #if !defined(_WIN32_WINNT)
00027     // The following Windows API function is declared explicitly;
00028     // otherwise any user would have to specify /D_WIN32_WINNT=0x0400
00029     extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
00030     #endif
00031 #else /* if not _WIN32||_WIN64 */
00032     #include <pthread.h>
00033 #endif /* _WIN32||_WIN64 */
00034 
00035 #include <new>
00036 #include "aligned_space.h"
00037 #include "tbb_stddef.h"
00038 #include "tbb_profiling.h"
00039 
00040 namespace tbb {
00042 
00044 class recursive_mutex {
00045 public:
00047     recursive_mutex() {
00048 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00049         internal_construct();
00050 #else
00051   #if _WIN32||_WIN64
00052         InitializeCriticalSection(&impl);
00053   #else
00054         pthread_mutexattr_t mtx_attr;
00055         int error_code = pthread_mutexattr_init( &mtx_attr );
00056         if( error_code )
00057             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
00058 
00059         pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
00060         error_code = pthread_mutex_init( &impl, &mtx_attr );
00061         if( error_code )
00062             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
00063 
00064         pthread_mutexattr_destroy( &mtx_attr );
00065   #endif /* _WIN32||_WIN64*/
00066 #endif /* TBB_USE_ASSERT */
00067     };
00068 
00069     ~recursive_mutex() {
00070 #if TBB_USE_ASSERT
00071         internal_destroy();
00072 #else
00073   #if _WIN32||_WIN64
00074         DeleteCriticalSection(&impl);
00075   #else
00076         pthread_mutex_destroy(&impl); 
00077 
00078   #endif /* _WIN32||_WIN64 */
00079 #endif /* TBB_USE_ASSERT */
00080     };
00081 
00082     class scoped_lock;
00083     friend class scoped_lock;
00084 
00086 
00088     class scoped_lock: internal::no_copy {
00089     public:
00091         scoped_lock() : my_mutex(NULL) {};
00092 
00094         scoped_lock( recursive_mutex& mutex ) {
00095 #if TBB_USE_ASSERT
00096             my_mutex = &mutex; 
00097 #endif /* TBB_USE_ASSERT */
00098             acquire( mutex );
00099         }
00100 
00102         ~scoped_lock() {
00103             if( my_mutex ) 
00104                 release();
00105         }
00106 
00108         void acquire( recursive_mutex& mutex ) {
00109 #if TBB_USE_ASSERT
00110             internal_acquire( mutex );
00111 #else
00112             my_mutex = &mutex;
00113             mutex.lock();
00114 #endif /* TBB_USE_ASSERT */
00115         }
00116 
00118         bool try_acquire( recursive_mutex& mutex ) {
00119 #if TBB_USE_ASSERT
00120             return internal_try_acquire( mutex );
00121 #else
00122             bool result = mutex.try_lock();
00123             if( result )
00124                 my_mutex = &mutex;
00125             return result;
00126 #endif /* TBB_USE_ASSERT */
00127         }
00128 
00130         void release() {
00131 #if TBB_USE_ASSERT
00132             internal_release();
00133 #else
00134             my_mutex->unlock();
00135             my_mutex = NULL;
00136 #endif /* TBB_USE_ASSERT */
00137         }
00138 
00139     private:
00141         recursive_mutex* my_mutex;
00142 
00144         void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
00145 
00147         bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
00148 
00150         void __TBB_EXPORTED_METHOD internal_release();
00151 
00152         friend class recursive_mutex;
00153     };
00154 
00155     // Mutex traits
00156     static const bool is_rw_mutex = false;
00157     static const bool is_recursive_mutex = true;
00158     static const bool is_fair_mutex = false;
00159 
00160     // C++0x compatibility interface
00161     
00163     void lock() {
00164 #if TBB_USE_ASSERT
00165         aligned_space<scoped_lock,1> tmp;
00166         new(tmp.begin()) scoped_lock(*this);
00167 #else
00168   #if _WIN32||_WIN64
00169         EnterCriticalSection(&impl);
00170   #else
00171         pthread_mutex_lock(&impl);
00172   #endif /* _WIN32||_WIN64 */
00173 #endif /* TBB_USE_ASSERT */
00174     }
00175 
00177 
00178     bool try_lock() {
00179 #if TBB_USE_ASSERT
00180         aligned_space<scoped_lock,1> tmp;
00181         return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
00182 #else        
00183   #if _WIN32||_WIN64
00184         return TryEnterCriticalSection(&impl)!=0;
00185   #else
00186         return pthread_mutex_trylock(&impl)==0;
00187   #endif /* _WIN32||_WIN64 */
00188 #endif /* TBB_USE_ASSERT */
00189     }
00190 
00192     void unlock() {
00193 #if TBB_USE_ASSERT
00194         aligned_space<scoped_lock,1> tmp;
00195         scoped_lock& s = *tmp.begin();
00196         s.my_mutex = this;
00197         s.internal_release();
00198 #else
00199   #if _WIN32||_WIN64
00200         LeaveCriticalSection(&impl);
00201   #else
00202         pthread_mutex_unlock(&impl);
00203   #endif /* _WIN32||_WIN64 */
00204 #endif /* TBB_USE_ASSERT */
00205     }
00206 
00208   #if _WIN32||_WIN64
00209     typedef LPCRITICAL_SECTION native_handle_type;
00210   #else
00211     typedef pthread_mutex_t* native_handle_type;
00212   #endif
00213     native_handle_type native_handle() { return (native_handle_type) &impl; }
00214 
00215 private:
00216 #if _WIN32||_WIN64
00217     CRITICAL_SECTION impl;
00218     enum state_t {
00219         INITIALIZED=0x1234,
00220         DESTROYED=0x789A,
00221     } state;
00222 #else
00223     pthread_mutex_t impl;
00224 #endif /* _WIN32||_WIN64 */
00225 
00227     void __TBB_EXPORTED_METHOD internal_construct();
00228 
00230     void __TBB_EXPORTED_METHOD internal_destroy();
00231 };
00232 
00233 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
00234 
00235 } // namespace tbb 
00236 
00237 #endif /* __TBB_recursive_mutex_H */

Copyright © 2005-2010 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.