BRE12
critical_section.h
1 /*
2  Copyright 2005-2016 Intel Corporation. All Rights Reserved.
3 
4  This file is part of Threading Building Blocks. Threading Building Blocks is free software;
5  you can redistribute it and/or modify it under the terms of the GNU General Public License
6  version 2 as published by the Free Software Foundation. Threading Building Blocks is
7  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  See the GNU General Public License for more details. You should have received a copy of
10  the GNU General Public License along with Threading Building Blocks; if not, write to the
11  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12 
13  As a special exception, you may use this file as part of a free software library without
14  restriction. Specifically, if other files instantiate templates or use macros or inline
15  functions from this file, or you compile this file and link it with other files to produce
16  an executable, this file does not by itself cause the resulting executable to be covered
17  by the GNU General Public License. This exception does not however invalidate any other
18  reasons why the executable file might be covered by the GNU General Public License.
19 */
20 
21 #ifndef _TBB_CRITICAL_SECTION_H_
22 #define _TBB_CRITICAL_SECTION_H_
23 
24 #if _WIN32||_WIN64
25 #include "machine/windows_api.h"
26 #else
27 #include <pthread.h>
28 #include <errno.h>
29 #endif // _WIN32||WIN64
30 
31 #include "tbb_stddef.h"
32 #include "tbb_thread.h"
33 #include "tbb_exception.h"
34 
35 #include "tbb_profiling.h"
36 
37 namespace tbb {
38 
39  namespace internal {
40 class critical_section_v4 : internal::no_copy {
41 #if _WIN32||_WIN64
42  CRITICAL_SECTION my_impl;
43 #else
44  pthread_mutex_t my_impl;
45 #endif
46  tbb_thread::id my_tid;
47 public:
48 
49  void __TBB_EXPORTED_METHOD internal_construct();
50 
52 #if _WIN32||_WIN64
53  InitializeCriticalSectionEx( &my_impl, 4000, 0 );
54 #else
55  pthread_mutex_init(&my_impl, NULL);
56 #endif
57  internal_construct();
58  }
59 
61  __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held critical section");
62 #if _WIN32||_WIN64
63  DeleteCriticalSection(&my_impl);
64 #else
65  pthread_mutex_destroy(&my_impl);
66 #endif
67  }
68 
69  class scoped_lock : internal::no_copy {
70  private:
71  critical_section_v4 &my_crit;
72  public:
73  scoped_lock( critical_section_v4& lock_me) :my_crit(lock_me) {
74  my_crit.lock();
75  }
76 
77  ~scoped_lock() {
78  my_crit.unlock();
79  }
80  };
81 
82  void lock() {
83  tbb_thread::id local_tid = this_tbb_thread::get_id();
84  if(local_tid == my_tid) throw_exception( eid_improper_lock );
85 #if _WIN32||_WIN64
86  EnterCriticalSection( &my_impl );
87 #else
88  int rval = pthread_mutex_lock(&my_impl);
89  __TBB_ASSERT_EX(!rval, "critical_section::lock: pthread_mutex_lock failed");
90 #endif
91  __TBB_ASSERT(my_tid == tbb_thread::id(), NULL);
92  my_tid = local_tid;
93  }
94 
95  bool try_lock() {
96  bool gotlock;
97  tbb_thread::id local_tid = this_tbb_thread::get_id();
98  if(local_tid == my_tid) return false;
99 #if _WIN32||_WIN64
100  gotlock = TryEnterCriticalSection( &my_impl ) != 0;
101 #else
102  int rval = pthread_mutex_trylock(&my_impl);
103  // valid returns are 0 (locked) and [EBUSY]
104  __TBB_ASSERT(rval == 0 || rval == EBUSY, "critical_section::trylock: pthread_mutex_trylock failed");
105  gotlock = rval == 0;
106 #endif
107  if(gotlock) {
108  my_tid = local_tid;
109  }
110  return gotlock;
111  }
112 
113  void unlock() {
114  __TBB_ASSERT(this_tbb_thread::get_id() == my_tid, "thread unlocking critical_section is not thread that locked it");
115  my_tid = tbb_thread::id();
116 #if _WIN32||_WIN64
117  LeaveCriticalSection( &my_impl );
118 #else
119  int rval = pthread_mutex_unlock(&my_impl);
120  __TBB_ASSERT_EX(!rval, "critical_section::unlock: pthread_mutex_unlock failed");
121 #endif
122  }
123 
124  static const bool is_rw_mutex = false;
125  static const bool is_recursive_mutex = false;
126  static const bool is_fair_mutex = true;
127 }; // critical_section_v4
128 } // namespace internal
130 
131 __TBB_DEFINE_PROFILING_SET_NAME(critical_section)
132 } // namespace tbb
133 #endif // _TBB_CRITICAL_SECTION_H_
Definition: critical_section.h:40
Definition: _flow_graph_async_msg_impl.h:32
Definition: tbb_thread.h:233
The namespace tbb contains all components of the library.
Definition: parallel_for.h:44
Definition: critical_section.h:69