|
libpsynth 0.2.1
|
00001 00026 /* 00027 * Copyright (C) 2009 Juan Pedro BolĂvar Puente 00028 * 00029 * This file is part of Psychosynth. 00030 * 00031 * Psychosynth is free software: you can redistribute it and/or modify 00032 * it under the terms of the GNU General Public License as published by 00033 * the Free Software Foundation, either version 3 of the License, or 00034 * (at your option) any later version. 00035 * 00036 * Psychosynth is distributed in the hope that it will be useful, 00037 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00038 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00039 * GNU General Public License for more details. 00040 * 00041 * You should have received a copy of the GNU General Public License 00042 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00043 * 00044 */ 00045 00046 #ifndef PSYNTH_THREADS_H_ 00047 #define PSYNTH_THREADS_H_ 00048 00049 #include <cassert> 00050 #include <psynth/base/util.hpp> 00051 00052 #define PSYNTH_DEFAULT_THREADING \ 00053 psynth::base::default_object_lockable::type 00054 #define PSYNTH_DEFAULT_NONOBJ_THREADING \ 00055 psynth::base::default_class_lockable::type 00056 00057 #ifndef PSYNTH_DEFAULT_MUTEX 00058 #include <mutex> 00059 #define PSYNTH_DEFAULT_MUTEX std::recursive_mutex 00060 #endif 00061 00062 namespace psynth 00063 { 00064 namespace base 00065 { 00066 00070 template <class Mutex, typename... Args> 00071 std::unique_lock<Mutex> make_unique_lock (Mutex& lock, Args... args) 00072 { 00073 return std::unique_lock<Mutex> (lock, args...); 00074 } 00075 00083 template <class Mutex = std::mutex> 00084 struct try_lock_guard 00085 { 00086 typedef std::unique_lock<Mutex> guard_type; 00087 00088 guard_type default_guard () 00089 { return guard_type (_mutex, std::try_to_lock); } 00090 00091 template <typename... Args> 00092 guard_type guard (Args... args) 00093 { return guard_type (_mutex, args...); } 00094 00095 void lock () 00096 { _mutex.lock (); } 00097 00098 bool try_lock () 00099 { return _mutex.try_lock (); } 00100 00101 void unlock () 00102 { _mutex.unlock (); } 00103 00104 private: 00105 Mutex _mutex; 00106 }; 00107 00108 00112 template <class Mutex = std::mutex> 00113 struct lock_guard : public try_lock_guard<Mutex> 00114 { 00115 typedef std::unique_lock<Mutex> guard_type; 00116 00117 guard_type default_guard () 00118 { return guard_type (_mutex); } 00119 00120 private: 00121 Mutex _mutex; 00122 }; 00123 00124 00128 template <class Mutex = std::mutex> 00129 struct no_lock_guard 00130 { 00131 struct guard_type 00132 { 00133 bool owns_lock () { return true; } 00134 }; 00135 00136 guard_type default_guard () { return {}; } 00137 template <typename... Args> 00138 guard_type guard (Args...) { assert (false); return {}; } 00139 void lock () { assert (false); } 00140 bool try_lock () { assert (false); return false; } 00141 void unlock () { assert (false); }; 00142 }; 00143 00144 00145 template <class T> 00146 class no_threading 00147 { 00148 public: 00149 typedef T volatile_type; 00150 00151 struct lock 00152 { 00153 lock () {} 00154 explicit lock (const no_threading& host) {} 00155 explicit lock (const no_threading* host) {} 00156 }; 00157 00158 private: 00159 }; 00160 00161 template <class T> 00162 class lockable_base 00163 { 00164 public: 00165 typedef volatile T volatile_type; 00166 }; 00167 00168 template <class T, class Mutex = PSYNTH_DEFAULT_MUTEX> 00169 class object_lockable : public lockable_base<T> 00170 { 00171 public: 00172 class lock : public boost::noncopyable 00173 { 00174 public: 00175 lock (const object_lockable& host) 00176 : _host (host) 00177 { _host._mutex.lock (); } 00178 00179 lock (const object_lockable* host) 00180 : _host (*host) 00181 { _host._mutex.lock (); } 00182 00183 ~lock () 00184 { _host._mutex.unlock (); } 00185 00186 private: 00187 const object_lockable& _host; 00188 }; 00189 00190 private: 00191 mutable Mutex _mutex; 00192 }; 00193 00194 template <class T, class Mutex = PSYNTH_DEFAULT_MUTEX> 00195 class class_lockable : public lockable_base<T> 00196 { 00197 public: 00198 class lock : public boost::noncopyable 00199 { 00200 public: 00201 lock () 00202 { s_init._mutex.lock (); } 00203 00204 lock (const class_lockable& host) 00205 { s_init._mutex.lock (); } 00206 00207 lock (const class_lockable* host) 00208 { s_init._mutex.lock (); } 00209 00210 ~lock () 00211 { s_init._mutex.unlock (); } 00212 }; 00213 00214 private: 00215 struct initializer 00216 { 00217 bool _is_init; 00218 Mutex _mutex; 00219 00220 initializer () 00221 : _is_init (false) 00222 { _is_init = true; } 00223 00224 ~initializer () 00225 { assert (_is_init); } 00226 }; 00227 00228 static initializer s_init; 00229 }; 00230 00231 template<class T, class M> 00232 typename class_lockable<T, M>::initializer class_lockable<T, M>::s_init; 00233 00234 typedef 00235 tpl_bind_snd<object_lockable, PSYNTH_DEFAULT_MUTEX> 00236 default_object_lockable; 00237 00238 typedef 00239 tpl_bind_snd<class_lockable, PSYNTH_DEFAULT_MUTEX> 00240 default_class_lockable; 00241 00242 } /* namespace base */ 00243 } /* namespace psynth */ 00244 00245 #endif /* PSYNTH_THREADS_H_ */
1.7.4