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