recursive_mutex.h Source File

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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.