STXXL  1.4-dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mutex.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/common/mutex.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Roman Dementiev <[email protected]>
7  * Copyright (C) 2008 Andreas Beckmann <[email protected]>
8  * Copyright (C) 2013 Timo Bingmann <[email protected]>
9  *
10  * Distributed under the Boost Software License, Version 1.0.
11  * (See accompanying file LICENSE_1_0.txt or copy at
12  * http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #ifndef STXXL_COMMON_MUTEX_HEADER
16 #define STXXL_COMMON_MUTEX_HEADER
17 
18 #include <stxxl/bits/config.h>
19 #include <stxxl/bits/namespace.h>
20 
21 #if STXXL_STD_THREADS && STXXL_WINDOWS && STXXL_MSVC >= 1700
22 #include <atomic>
23 #endif
24 
25 #if STXXL_STD_THREADS
26  #include <mutex>
27 #elif STXXL_BOOST_THREADS
28  #include <boost/thread/mutex.hpp>
29 #elif STXXL_POSIX_THREADS
30  #include <pthread.h>
31 
32  #include <stxxl/bits/noncopyable.h>
34 #else
35  #error "Thread implementation not detected."
36 #endif
37 
39 
40 #if STXXL_STD_THREADS
41 
42 typedef std::mutex mutex;
43 
44 #elif STXXL_BOOST_THREADS
45 
46 typedef boost::mutex mutex;
47 
48 #elif STXXL_POSIX_THREADS
49 
50 class mutex : private noncopyable
51 {
52  //! mutex handle
53  pthread_mutex_t m_mutex;
54 
55 public:
56  //! construct unlocked mutex
58  {
59  STXXL_CHECK_PTHREAD_CALL(pthread_mutex_init(&m_mutex, NULL));
60  }
61  //! destroy mutex handle
63  {
64  // try simple delete first
65  int res = pthread_mutex_destroy(&m_mutex);
66  if (res == 0) return;
67 
68  // try to lock and unlock mutex
69  res = pthread_mutex_trylock(&m_mutex);
70 
71  if (res == 0 || res == EBUSY) {
72  STXXL_CHECK_PTHREAD_CALL(pthread_mutex_unlock(&m_mutex));
73  }
74  else {
75  STXXL_THROW_ERRNO2(resource_error, "pthread_mutex_trylock() failed", res);
76  }
77 
78  STXXL_CHECK_PTHREAD_CALL(pthread_mutex_destroy(&m_mutex));
79  }
80  //! lock mutex, may block
81  void lock()
82  {
83  STXXL_CHECK_PTHREAD_CALL(pthread_mutex_lock(&m_mutex));
84  }
85  //! unlock mutex
86  void unlock()
87  {
88  STXXL_CHECK_PTHREAD_CALL(pthread_mutex_unlock(&m_mutex));
89  }
90  //! return platform specific handle
91  pthread_mutex_t & native_handle()
92  {
93  return m_mutex;
94  }
95 };
96 
97 #endif // STXXL_POSIX_THREADS
98 
99 #if STXXL_STD_THREADS && STXXL_WINDOWS && STXXL_MSVC >= 1700
100 
101 class spin_lock;
102 typedef spin_lock fastmutex;
103 
104 #else
105 
106 typedef mutex fastmutex;
107 
108 #endif
109 
110 #if STXXL_STD_THREADS
111 
112 typedef std::unique_lock<std::mutex> scoped_mutex_lock;
113 typedef std::unique_lock<fastmutex> scoped_fast_mutex_lock;
114 
115 #elif STXXL_BOOST_THREADS
116 
117 typedef boost::mutex::scoped_lock scoped_mutex_lock;
118 typedef boost::mutex::scoped_lock scoped_fast_mutex_lock;
119 
120 #else
121 
122 //! Aquire a lock that's valid until the end of scope.
124 {
125  //! mutex reference
127 
128  //! marker if already unlocked by this thread (needs no synchronization)
129  bool is_locked;
130 
131 public:
132  //! lock mutex
134  : m_mutex(m), is_locked(true)
135  {
136  m_mutex.lock();
137  }
138  //! unlock mutex hold when object goes out of scope.
140  {
141  unlock();
142  }
143  //! unlock mutex hold prematurely
144  void unlock()
145  {
146  if (is_locked) {
147  is_locked = false;
148  m_mutex.unlock();
149  }
150  }
151  //! return platform specific handle
152  pthread_mutex_t & native_handle()
153  {
154  return m_mutex.native_handle();
155  }
156 };
157 
159 
160 #endif
161 
162 #if STXXL_STD_THREADS && STXXL_WINDOWS && STXXL_MSVC >= 1700
163 
164 class spin_lock
165 {
166 public:
167 #if STXXL_MSVC < 1800
168  spin_lock()
169  {
170  lck.clear(std::memory_order_release);
171  }
172 #else
173  spin_lock()
174  { }
175 #endif
176 
177  void lock()
178  {
179  while (lck.test_and_set(std::memory_order_acquire))
180  { }
181  }
182 
183  void unlock()
184  {
185  lck.clear(std::memory_order_release);
186  }
187 
188 private:
189 #if STXXL_MSVC >= 1800
190  std::atomic_flag lck = ATOMIC_FLAG_INIT;
191  spin_lock(const spin_lock&) = delete;
192  spin_lock& operator = (const spin_lock&) = delete;
193 #else
194  std::atomic_flag lck;
195  spin_lock(const spin_lock&);
196  spin_lock& operator = (const spin_lock&);
197 #endif
198 };
199 
200 #endif
202 
203 #endif // !STXXL_COMMON_MUTEX_HEADER
~mutex()
destroy mutex handle
Definition: mutex.h:62
scoped_mutex_lock(mutex &m)
lock mutex
Definition: mutex.h:133
#define STXXL_CHECK_PTHREAD_CALL(expr)
Checks pthread call, if return != 0, throws stxxl::resource_error with "Error in [function] : [pthrea...
void unlock()
unlock mutex hold prematurely
Definition: mutex.h:144
bool is_locked
marker if already unlocked by this thread (needs no synchronization)
Definition: mutex.h:129
#define STXXL_THROW_ERRNO2(exception_type, error_message, errno_value)
Throws exception_type with &quot;Error in [function] : [error_message] : [errno_value message]&quot;.
void lock()
lock mutex, may block
Definition: mutex.h:81
~scoped_mutex_lock()
unlock mutex hold when object goes out of scope.
Definition: mutex.h:139
pthread_mutex_t & native_handle()
return platform specific handle
Definition: mutex.h:152
Aquire a lock that&#39;s valid until the end of scope.
Definition: mutex.h:123
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
pthread_mutex_t m_mutex
mutex handle
Definition: mutex.h:53
mutex()
construct unlocked mutex
Definition: mutex.h:57
scoped_mutex_lock scoped_fast_mutex_lock
Definition: mutex.h:158
mutex fastmutex
Definition: mutex.h:106
mutex & m_mutex
mutex reference
Definition: mutex.h:126
void unlock()
unlock mutex
Definition: mutex.h:86
pthread_mutex_t & native_handle()
return platform specific handle
Definition: mutex.h:91
#define STXXL_END_NAMESPACE
Definition: namespace.h:17