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

- File List
- File Members

# recursive_mutex.h

    00001 /*
    00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
    00003
    00004     This file is part of Threading Building Blocks.
    00005
    00006     Threading Building Blocks is free software; you can redistribute it
    00007     and/or modify it under the terms of the GNU General Public License
    00008     version 2 as published by the Free Software Foundation.
    00009
    00010     Threading Building Blocks is distributed in the hope that it will be
    00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013     GNU General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with Threading Building Blocks; if not, write to the Free Software
    00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00018
    00019     As a special exception, you may use this file as part of a free software
    00020     library without restriction.  Specifically, if other files instantiate
    00021     templates or use macros or inline functions from this file, or you compile
    00022     this file and link it with other files to produce an executable, this
    00023     file does not by itself cause the resulting executable to be covered by
    00024     the GNU General Public License.  This exception does not however
    00025     invalidate any other reasons why the executable file might be covered by
    00026     the GNU General Public License.
    00027 */
    00028
    00029 #ifndef __TBB_recursive_mutex_H
    00030 #define __TBB_recursive_mutex_H
    00031
    00032 #if _WIN32||_WIN64
    00033 #include "machine/windows_api.h"
    00034 #else
    00035 #include <pthread.h>
    00036 #endif /* _WIN32||_WIN64 */
    00037
    00038 #include <new>
    00039 #include "aligned_space.h"
    00040 #include "tbb_stddef.h"
    00041 #include "tbb_profiling.h"
    00042
    00043 namespace tbb {
    00045
    00047 class recursive_mutex {
    00048 public:
    00050     recursive_mutex() {
    00051 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
    00052         internal_construct();
    00053 #else
    00054   #if _WIN32||_WIN64
    00055         InitializeCriticalSectionEx(&impl, 4000, 0);
    00056   #else
    00057         pthread_mutexattr_t mtx_attr;
    00058         int error_code = pthread_mutexattr_init( &mtx_attr );
    00059         if( error_code )
    00060             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
    00061
    00062         pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
    00063         error_code = pthread_mutex_init( &impl, &mtx_attr );
    00064         if( error_code )
    00065             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
    00066
    00067         pthread_mutexattr_destroy( &mtx_attr );
    00068   #endif /* _WIN32||_WIN64*/
    00069 #endif /* TBB_USE_ASSERT */
    00070     };
    00071
    00072     ~recursive_mutex() {
    00073 #if TBB_USE_ASSERT
    00074         internal_destroy();
    00075 #else
    00076   #if _WIN32||_WIN64
    00077         DeleteCriticalSection(&impl);
    00078   #else
    00079         pthread_mutex_destroy(&impl);
    00080
    00081   #endif /* _WIN32||_WIN64 */
    00082 #endif /* TBB_USE_ASSERT */
    00083     };
    00084
    00085     class scoped_lock;
    00086     friend class scoped_lock;
    00087
    00089
    00091     class scoped_lock: internal::no_copy {
    00092     public:
    00094         scoped_lock() : my_mutex(NULL) {};
    00095
    00097         scoped_lock( recursive_mutex& mutex ) {
    00098 #if TBB_USE_ASSERT
    00099             my_mutex = &mutex;
    00100 #endif /* TBB_USE_ASSERT */
    00101             acquire( mutex );
    00102         }
    00103
    00105         ~scoped_lock() {
    00106             if( my_mutex )
    00107                 release();
    00108         }
    00109
    00111         void acquire( recursive_mutex& mutex ) {
    00112 #if TBB_USE_ASSERT
    00113             internal_acquire( mutex );
    00114 #else
    00115             my_mutex = &mutex;
    00116             mutex.lock();
    00117 #endif /* TBB_USE_ASSERT */
    00118         }
    00119
    00121         bool try_acquire( recursive_mutex& mutex ) {
    00122 #if TBB_USE_ASSERT
    00123             return internal_try_acquire( mutex );
    00124 #else
    00125             bool result = mutex.try_lock();
    00126             if( result )
    00127                 my_mutex = &mutex;
    00128             return result;
    00129 #endif /* TBB_USE_ASSERT */
    00130         }
    00131
    00133         void release() {
    00134 #if TBB_USE_ASSERT
    00135             internal_release();
    00136 #else
    00137             my_mutex->unlock();
    00138             my_mutex = NULL;
    00139 #endif /* TBB_USE_ASSERT */
    00140         }
    00141
    00142     private:
    00144         recursive_mutex* my_mutex;
    00145
    00147         void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
    00148
    00150         bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
    00151
    00153         void __TBB_EXPORTED_METHOD internal_release();
    00154
    00155         friend class recursive_mutex;
    00156     };
    00157
    00158     // Mutex traits
    00159     static const bool is_rw_mutex = false;
    00160     static const bool is_recursive_mutex = true;
    00161     static const bool is_fair_mutex = false;
    00162
    00163     // C++0x compatibility interface
    00164
    00166     void lock() {
    00167 #if TBB_USE_ASSERT
    00168         aligned_space<scoped_lock,1> tmp;
    00169         new(tmp.begin()) scoped_lock(*this);
    00170 #else
    00171   #if _WIN32||_WIN64
    00172         EnterCriticalSection(&impl);
    00173   #else
    00174         pthread_mutex_lock(&impl);
    00175   #endif /* _WIN32||_WIN64 */
    00176 #endif /* TBB_USE_ASSERT */
    00177     }
    00178
    00180
    00181     bool try_lock() {
    00182 #if TBB_USE_ASSERT
    00183         aligned_space<scoped_lock,1> tmp;
    00184         return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
    00185 #else
    00186   #if _WIN32||_WIN64
    00187         return TryEnterCriticalSection(&impl)!=0;
    00188   #else
    00189         return pthread_mutex_trylock(&impl)==0;
    00190   #endif /* _WIN32||_WIN64 */
    00191 #endif /* TBB_USE_ASSERT */
    00192     }
    00193
    00195     void unlock() {
    00196 #if TBB_USE_ASSERT
    00197         aligned_space<scoped_lock,1> tmp;
    00198         scoped_lock& s = *tmp.begin();
    00199         s.my_mutex = this;
    00200         s.internal_release();
    00201 #else
    00202   #if _WIN32||_WIN64
    00203         LeaveCriticalSection(&impl);
    00204   #else
    00205         pthread_mutex_unlock(&impl);
    00206   #endif /* _WIN32||_WIN64 */
    00207 #endif /* TBB_USE_ASSERT */
    00208     }
    00209
    00211   #if _WIN32||_WIN64
    00212     typedef LPCRITICAL_SECTION native_handle_type;
    00213   #else
    00214     typedef pthread_mutex_t* native_handle_type;
    00215   #endif
    00216     native_handle_type native_handle() { return (native_handle_type) &impl; }
    00217
    00218 private:
    00219 #if _WIN32||_WIN64
    00220     CRITICAL_SECTION impl;
    00221     enum state_t {
    00222         INITIALIZED=0x1234,
    00223         DESTROYED=0x789A,
    00224     } state;
    00225 #else
    00226     pthread_mutex_t impl;
    00227 #endif /* _WIN32||_WIN64 */
    00228
    00230     void __TBB_EXPORTED_METHOD internal_construct();
    00231
    00233     void __TBB_EXPORTED_METHOD internal_destroy();
    00234 };
    00235
    00236 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
    00237
    00238 } // namespace tbb
    00239
    00240 #endif /* __TBB_recursive_mutex_H */

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