recursive_mutex.h

00001 /*
00002     Copyright 2005-2011 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 "machine/windows_api.h"
00026 #else
00027 #include <pthread.h>
00028 #endif /* _WIN32||_WIN64 */
00029 
00030 #include <new>
00031 #include "aligned_space.h"
00032 #include "tbb_stddef.h"
00033 #include "tbb_profiling.h"
00034 
00035 namespace tbb {
00037 
00039 class recursive_mutex {
00040 public:
00042     recursive_mutex() {
00043 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00044         internal_construct();
00045 #else
00046   #if _WIN32||_WIN64
00047         InitializeCriticalSection(&impl);
00048   #else
00049         pthread_mutexattr_t mtx_attr;
00050         int error_code = pthread_mutexattr_init( &mtx_attr );
00051         if( error_code )
00052             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
00053 
00054         pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
00055         error_code = pthread_mutex_init( &impl, &mtx_attr );
00056         if( error_code )
00057             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
00058 
00059         pthread_mutexattr_destroy( &mtx_attr );
00060   #endif /* _WIN32||_WIN64*/
00061 #endif /* TBB_USE_ASSERT */
00062     };
00063 
00064     ~recursive_mutex() {
00065 #if TBB_USE_ASSERT
00066         internal_destroy();
00067 #else
00068   #if _WIN32||_WIN64
00069         DeleteCriticalSection(&impl);
00070   #else
00071         pthread_mutex_destroy(&impl); 
00072 
00073   #endif /* _WIN32||_WIN64 */
00074 #endif /* TBB_USE_ASSERT */
00075     };
00076 
00077     class scoped_lock;
00078     friend class scoped_lock;
00079 
00081 
00083     class scoped_lock: internal::no_copy {
00084     public:
00086         scoped_lock() : my_mutex(NULL) {};
00087 
00089         scoped_lock( recursive_mutex& mutex ) {
00090 #if TBB_USE_ASSERT
00091             my_mutex = &mutex; 
00092 #endif /* TBB_USE_ASSERT */
00093             acquire( mutex );
00094         }
00095 
00097         ~scoped_lock() {
00098             if( my_mutex ) 
00099                 release();
00100         }
00101 
00103         void acquire( recursive_mutex& mutex ) {
00104 #if TBB_USE_ASSERT
00105             internal_acquire( mutex );
00106 #else
00107             my_mutex = &mutex;
00108             mutex.lock();
00109 #endif /* TBB_USE_ASSERT */
00110         }
00111 
00113         bool try_acquire( recursive_mutex& mutex ) {
00114 #if TBB_USE_ASSERT
00115             return internal_try_acquire( mutex );
00116 #else
00117             bool result = mutex.try_lock();
00118             if( result )
00119                 my_mutex = &mutex;
00120             return result;
00121 #endif /* TBB_USE_ASSERT */
00122         }
00123 
00125         void release() {
00126 #if TBB_USE_ASSERT
00127             internal_release();
00128 #else
00129             my_mutex->unlock();
00130             my_mutex = NULL;
00131 #endif /* TBB_USE_ASSERT */
00132         }
00133 
00134     private:
00136         recursive_mutex* my_mutex;
00137 
00139         void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
00140 
00142         bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
00143 
00145         void __TBB_EXPORTED_METHOD internal_release();
00146 
00147         friend class recursive_mutex;
00148     };
00149 
00150     // Mutex traits
00151     static const bool is_rw_mutex = false;
00152     static const bool is_recursive_mutex = true;
00153     static const bool is_fair_mutex = false;
00154 
00155     // C++0x compatibility interface
00156     
00158     void lock() {
00159 #if TBB_USE_ASSERT
00160         aligned_space<scoped_lock,1> tmp;
00161         new(tmp.begin()) scoped_lock(*this);
00162 #else
00163   #if _WIN32||_WIN64
00164         EnterCriticalSection(&impl);
00165   #else
00166         pthread_mutex_lock(&impl);
00167   #endif /* _WIN32||_WIN64 */
00168 #endif /* TBB_USE_ASSERT */
00169     }
00170 
00172 
00173     bool try_lock() {
00174 #if TBB_USE_ASSERT
00175         aligned_space<scoped_lock,1> tmp;
00176         return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
00177 #else        
00178   #if _WIN32||_WIN64
00179         return TryEnterCriticalSection(&impl)!=0;
00180   #else
00181         return pthread_mutex_trylock(&impl)==0;
00182   #endif /* _WIN32||_WIN64 */
00183 #endif /* TBB_USE_ASSERT */
00184     }
00185 
00187     void unlock() {
00188 #if TBB_USE_ASSERT
00189         aligned_space<scoped_lock,1> tmp;
00190         scoped_lock& s = *tmp.begin();
00191         s.my_mutex = this;
00192         s.internal_release();
00193 #else
00194   #if _WIN32||_WIN64
00195         LeaveCriticalSection(&impl);
00196   #else
00197         pthread_mutex_unlock(&impl);
00198   #endif /* _WIN32||_WIN64 */
00199 #endif /* TBB_USE_ASSERT */
00200     }
00201 
00203   #if _WIN32||_WIN64
00204     typedef LPCRITICAL_SECTION native_handle_type;
00205   #else
00206     typedef pthread_mutex_t* native_handle_type;
00207   #endif
00208     native_handle_type native_handle() { return (native_handle_type) &impl; }
00209 
00210 private:
00211 #if _WIN32||_WIN64
00212     CRITICAL_SECTION impl;
00213     enum state_t {
00214         INITIALIZED=0x1234,
00215         DESTROYED=0x789A,
00216     } state;
00217 #else
00218     pthread_mutex_t impl;
00219 #endif /* _WIN32||_WIN64 */
00220 
00222     void __TBB_EXPORTED_METHOD internal_construct();
00223 
00225     void __TBB_EXPORTED_METHOD internal_destroy();
00226 };
00227 
00228 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
00229 
00230 } // namespace tbb 
00231 
00232 #endif /* __TBB_recursive_mutex_H */

Copyright © 2005-2011 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.