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

- File List
- File Members

# 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_mutex_H
    00030 #define __TBB_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 {
    00044
    00046
    00048 class mutex {
    00049 public:
    00051     mutex() {
    00052 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
    00053     internal_construct();
    00054 #else
    00055   #if _WIN32||_WIN64
    00056         InitializeCriticalSectionEx(&impl, 4000, 0);
    00057   #else
    00058         int error_code = pthread_mutex_init(&impl,NULL);
    00059         if( error_code )
    00060             tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
    00061   #endif /* _WIN32||_WIN64*/
    00062 #endif /* TBB_USE_ASSERT */
    00063     };
    00064
    00065     ~mutex() {
    00066 #if TBB_USE_ASSERT
    00067         internal_destroy();
    00068 #else
    00069   #if _WIN32||_WIN64
    00070         DeleteCriticalSection(&impl);
    00071   #else
    00072         pthread_mutex_destroy(&impl);
    00073
    00074   #endif /* _WIN32||_WIN64 */
    00075 #endif /* TBB_USE_ASSERT */
    00076     };
    00077
    00078     class scoped_lock;
    00079     friend class scoped_lock;
    00080
    00082
    00084     class scoped_lock : internal::no_copy {
    00085     public:
    00087         scoped_lock() : my_mutex(NULL) {};
    00088
    00090         scoped_lock( mutex& mutex ) {
    00091             acquire( mutex );
    00092         }
    00093
    00095         ~scoped_lock() {
    00096             if( my_mutex )
    00097                 release();
    00098         }
    00099
    00101         void acquire( mutex& mutex ) {
    00102 #if TBB_USE_ASSERT
    00103             internal_acquire(mutex);
    00104 #else
    00105             mutex.lock();
    00106             my_mutex = &mutex;
    00107 #endif /* TBB_USE_ASSERT */
    00108         }
    00109
    00111         bool try_acquire( mutex& mutex ) {
    00112 #if TBB_USE_ASSERT
    00113             return internal_try_acquire (mutex);
    00114 #else
    00115             bool result = mutex.try_lock();
    00116             if( result )
    00117                 my_mutex = &mutex;
    00118             return result;
    00119 #endif /* TBB_USE_ASSERT */
    00120         }
    00121
    00123         void release() {
    00124 #if TBB_USE_ASSERT
    00125             internal_release ();
    00126 #else
    00127             my_mutex->unlock();
    00128             my_mutex = NULL;
    00129 #endif /* TBB_USE_ASSERT */
    00130         }
    00131
    00132     private:
    00134         mutex* my_mutex;
    00135
    00137         void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
    00138
    00140         bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
    00141
    00143         void __TBB_EXPORTED_METHOD internal_release();
    00144
    00145         friend class mutex;
    00146     };
    00147
    00148     // Mutex traits
    00149     static const bool is_rw_mutex = false;
    00150     static const bool is_recursive_mutex = false;
    00151     static const bool is_fair_mutex = false;
    00152
    00153     // ISO C++0x compatibility methods
    00154
    00156     void lock() {
    00157 #if TBB_USE_ASSERT
    00158         aligned_space<scoped_lock,1> tmp;
    00159         new(tmp.begin()) scoped_lock(*this);
    00160 #else
    00161   #if _WIN32||_WIN64
    00162         EnterCriticalSection(&impl);
    00163   #else
    00164         pthread_mutex_lock(&impl);
    00165   #endif /* _WIN32||_WIN64 */
    00166 #endif /* TBB_USE_ASSERT */
    00167     }
    00168
    00170
    00171     bool try_lock() {
    00172 #if TBB_USE_ASSERT
    00173         aligned_space<scoped_lock,1> tmp;
    00174         scoped_lock& s = *tmp.begin();
    00175         s.my_mutex = NULL;
    00176         return s.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     enum state_t {
    00211         INITIALIZED=0x1234,
    00212         DESTROYED=0x789A,
    00213         HELD=0x56CD
    00214     };
    00215 private:
    00216 #if _WIN32||_WIN64
    00217     CRITICAL_SECTION impl;
    00218     enum state_t state;
    00219 #else
    00220     pthread_mutex_t impl;
    00221 #endif /* _WIN32||_WIN64 */
    00222
    00224     void __TBB_EXPORTED_METHOD internal_construct();
    00225
    00227     void __TBB_EXPORTED_METHOD internal_destroy();
    00228
    00229 #if _WIN32||_WIN64
    00230 public:
    00232     void set_state( state_t to ) { state = to; }
    00233 #endif
    00234 };
    00235
    00236 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
    00237
    00238 } // namespace tbb
    00239
    00240 #endif /* __TBB_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.