mutex.h

00001 /*
00002     Copyright 2005-2009 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_mutex_H
00022 #define __TBB_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 
00032 #else /* if not _WIN32||_WIN64 */
00033 #include <pthread.h>
00034 namespace tbb { namespace internal {
00035 // Use this internal TBB function to throw an exception
00036 extern void handle_perror( int error_code, const char* what );
00037 } } //namespaces
00038 #endif /* _WIN32||_WIN64 */
00039 
00040 #include <new>
00041 #include "aligned_space.h"
00042 #include "tbb_stddef.h"
00043 #include "tbb_profiling.h"
00044 
00045 namespace tbb {
00046 
00048 
00050 class mutex {
00051 public:
00053     mutex() {
00054 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00055     internal_construct();
00056 #else
00057   #if _WIN32||_WIN64
00058         InitializeCriticalSection(&impl);
00059   #else
00060         int error_code = pthread_mutex_init(&impl,NULL);
00061         if( error_code )
00062             tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
00063   #endif /* _WIN32||_WIN64*/
00064 #endif /* TBB_USE_ASSERT */
00065     };
00066 
00067     ~mutex() {
00068 #if TBB_USE_ASSERT
00069         internal_destroy();
00070 #else
00071   #if _WIN32||_WIN64
00072         DeleteCriticalSection(&impl);
00073   #else
00074         pthread_mutex_destroy(&impl); 
00075 
00076   #endif /* _WIN32||_WIN64 */
00077 #endif /* TBB_USE_ASSERT */
00078     };
00079 
00080     class scoped_lock;
00081     friend class scoped_lock;
00082 
00084 
00086     class scoped_lock : internal::no_copy {
00087     public:
00089         scoped_lock() : my_mutex(NULL) {};
00090 
00092 
00093         scoped_lock( mutex& mutex ) {
00094             acquire( mutex );
00095         }
00096 
00098         ~scoped_lock() {
00099             if( my_mutex ) 
00100                 release();
00101         }
00102 
00104         void acquire( mutex& mutex ) {
00105 #if TBB_USE_ASSERT
00106             internal_acquire(mutex);
00107 #else
00108             mutex.lock();
00109             my_mutex = &mutex;
00110 #endif /* TBB_USE_ASSERT */
00111         }
00112 
00114         bool try_acquire( mutex& mutex ) {
00115 #if TBB_USE_ASSERT
00116             return internal_try_acquire (mutex);
00117 #else
00118             bool result = mutex.try_lock();
00119             if( result )
00120                 my_mutex = &mutex;
00121             return result;
00122 #endif /* TBB_USE_ASSERT */
00123         }
00124 
00126         void release() {
00127 #if TBB_USE_ASSERT
00128             internal_release ();
00129 #else
00130             my_mutex->unlock();
00131             my_mutex = NULL;
00132 #endif /* TBB_USE_ASSERT */
00133         }
00134 
00135     private:
00137         mutex* my_mutex;
00138 
00140         void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
00141 
00143         bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
00144 
00146         void __TBB_EXPORTED_METHOD internal_release();
00147 
00148         friend class mutex;
00149     };
00150 
00151     // Mutex traits
00152     static const bool is_rw_mutex = false;
00153     static const bool is_recursive_mutex = false;
00154     static const bool is_fair_mutex = false;
00155 
00156     // ISO C++0x compatibility methods
00157 
00159     void lock() {
00160 #if TBB_USE_ASSERT
00161         aligned_space<scoped_lock,1> tmp;
00162         new(tmp.begin()) scoped_lock(*this);
00163 #else
00164   #if _WIN32||_WIN64
00165         EnterCriticalSection(&impl);
00166   #else
00167         pthread_mutex_lock(&impl);
00168   #endif /* _WIN32||_WIN64 */
00169 #endif /* TBB_USE_ASSERT */
00170     }
00171 
00173 
00174     bool try_lock() {
00175 #if TBB_USE_ASSERT
00176         aligned_space<scoped_lock,1> tmp;
00177         scoped_lock& s = *tmp.begin();
00178         s.my_mutex = NULL;
00179         return s.internal_try_acquire(*this);
00180 #else
00181   #if _WIN32||_WIN64
00182         return TryEnterCriticalSection(&impl)!=0;
00183   #else
00184         return pthread_mutex_trylock(&impl)==0;
00185   #endif /* _WIN32||_WIN64 */
00186 #endif /* TBB_USE_ASSERT */
00187     }
00188 
00190     void unlock() {
00191 #if TBB_USE_ASSERT
00192         aligned_space<scoped_lock,1> tmp;
00193         scoped_lock& s = *tmp.begin();
00194         s.my_mutex = this;
00195         s.internal_release();
00196 #else
00197   #if _WIN32||_WIN64
00198         LeaveCriticalSection(&impl);
00199   #else
00200         pthread_mutex_unlock(&impl);
00201   #endif /* _WIN32||_WIN64 */
00202 #endif /* TBB_USE_ASSERT */
00203     }
00204 
00205 private:
00206 #if _WIN32||_WIN64
00207     CRITICAL_SECTION impl;    
00208     enum state_t {
00209         INITIALIZED=0x1234,
00210         DESTROYED=0x789A,
00211         HELD=0x56CD
00212     } state;
00213 #else
00214     pthread_mutex_t impl;
00215 #endif /* _WIN32||_WIN64 */
00216 
00218     void __TBB_EXPORTED_METHOD internal_construct();
00219 
00221     void __TBB_EXPORTED_METHOD internal_destroy();
00222 };
00223 
00224 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
00225 
00226 } // namespace tbb 
00227 
00228 #endif /* __TBB_mutex_H */

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