critical_section.h

00001 /*
00002     Copyright 2005-2010 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_CRITICAL_SECTION_H_
00022 #define _TBB_CRITICAL_SECTION_H_
00023 
00024 #if _WIN32||_WIN64
00025 #include <windows.h>
00026 #else
00027 #include <pthread.h>
00028 #include <errno.h>
00029 #endif  // _WIN32||WIN64
00030 
00031 #include "tbb_stddef.h"
00032 #include "tbb_thread.h"
00033 #include "tbb_exception.h"
00034 
00035 #include "tbb_profiling.h"
00036 
00037 namespace tbb {
00038 
00039     namespace internal {
00040 class critical_section_v4 : internal::no_copy {
00041 #if _WIN32||_WIN64
00042     CRITICAL_SECTION my_impl;
00043 #else
00044     pthread_mutex_t my_impl;
00045 #endif
00046     tbb_thread::id my_tid;
00047 public:
00048 
00049     void __TBB_EXPORTED_METHOD internal_construct();
00050 
00051     critical_section_v4() { 
00052 #if _WIN32||_WIN64
00053         InitializeCriticalSection(&my_impl);
00054 #else
00055         pthread_mutex_init(&my_impl, NULL);
00056 #endif
00057         internal_construct();
00058     }
00059 
00060     ~critical_section_v4() {
00061         __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held critical section");
00062 #if _WIN32||_WIN64
00063         DeleteCriticalSection(&my_impl); 
00064 #else
00065         pthread_mutex_destroy(&my_impl);
00066 #endif
00067     }
00068 
00069     class scoped_lock : internal::no_copy {
00070     private:
00071         critical_section_v4 &my_crit;
00072     public:
00073         scoped_lock( critical_section_v4& lock_me) :my_crit(lock_me) {
00074             my_crit.lock();
00075         }
00076 
00077         ~scoped_lock() {
00078             my_crit.unlock();
00079         }
00080     };
00081 
00082     void lock() { 
00083         tbb_thread::id local_tid = this_tbb_thread::get_id();
00084         if(local_tid == my_tid) throw_exception( eid_improper_lock );
00085 #if _WIN32||_WIN64
00086         EnterCriticalSection( &my_impl );
00087 #else
00088         int rval = pthread_mutex_lock(&my_impl);
00089         __TBB_ASSERT_EX(!rval, "critical_section::lock: pthread_mutex_lock failed");
00090 #endif
00091         __TBB_ASSERT(my_tid == tbb_thread::id(), NULL);
00092         my_tid = local_tid;
00093     }
00094 
00095     bool try_lock() {
00096         bool gotlock;
00097         tbb_thread::id local_tid = this_tbb_thread::get_id();
00098         if(local_tid == my_tid) return false;
00099 #if _WIN32||_WIN64
00100         gotlock = TryEnterCriticalSection( &my_impl ) != 0;
00101 #else
00102         int rval = pthread_mutex_trylock(&my_impl);
00103         // valid returns are 0 (locked) and [EBUSY]
00104         __TBB_ASSERT(rval == 0 || rval == EBUSY, "critical_section::trylock: pthread_mutex_trylock failed");
00105         gotlock = rval == 0;
00106 #endif
00107         if(gotlock)  {
00108             my_tid = local_tid;
00109         }
00110         return gotlock;
00111     }
00112 
00113     void unlock() {
00114         __TBB_ASSERT(this_tbb_thread::get_id() == my_tid, "thread unlocking critical_section is not thread that locked it");
00115         my_tid = tbb_thread::id();
00116 #if _WIN32||_WIN64
00117         LeaveCriticalSection( &my_impl );
00118 #else
00119         int rval = pthread_mutex_unlock(&my_impl);
00120         __TBB_ASSERT_EX(!rval, "critical_section::unlock: pthread_mutex_unlock failed");
00121 #endif
00122     }
00123 
00124     static const bool is_rw_mutex = false;
00125     static const bool is_recursive_mutex = false;
00126     static const bool is_fair_mutex = true;
00127 }; // critical_section_v4
00128 } // namespace internal
00129 typedef internal::critical_section_v4 critical_section;
00130 
00131 __TBB_DEFINE_PROFILING_SET_NAME(critical_section)
00132 } // namespace tbb
00133 #endif  // _TBB_CRITICAL_SECTION_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.