1 // Copyright (C) 2001-2003 2 // William E. Kempf 3 // 4 // Permission to use, copy, modify, distribute and sell this software 5 // and its documentation for any purpose is hereby granted without fee, 6 // provided that the above copyright notice appear in all copies and 7 // that both that copyright notice and this permission notice appear 8 // in supporting documentation. William E. Kempf makes no representations 9 // about the suitability of this software for any purpose. 10 // It is provided "as is" without express or implied warranty. 11 12 #ifndef BOOST_XLOCK_WEK070601_HPP 13 #define BOOST_XLOCK_WEK070601_HPP 14 15 #include <boost/thread/detail/config.hpp> 16 17 #include <boost/utility.hpp> 18 #include <boost/thread/exceptions.hpp> 19 20 namespace boost { 21 22 class condition; 23 struct xtime; 24 25 namespace detail { namespace thread { 26 27 template <typename Mutex> 28 class lock_ops : private noncopyable 29 { 30 private: lock_ops()31 lock_ops() { } 32 33 public: 34 typedef typename Mutex::cv_state lock_state; 35 lock(Mutex & m)36 static void lock(Mutex& m) 37 { 38 m.do_lock(); 39 } trylock(Mutex & m)40 static bool trylock(Mutex& m) 41 { 42 return m.do_trylock(); 43 } timedlock(Mutex & m,const xtime & xt)44 static bool timedlock(Mutex& m, const xtime& xt) 45 { 46 return m.do_timedlock(xt); 47 } unlock(Mutex & m)48 static void unlock(Mutex& m) 49 { 50 m.do_unlock(); 51 } lock(Mutex & m,lock_state & state)52 static void lock(Mutex& m, lock_state& state) 53 { 54 m.do_lock(state); 55 } unlock(Mutex & m,lock_state & state)56 static void unlock(Mutex& m, lock_state& state) 57 { 58 m.do_unlock(state); 59 } 60 }; 61 62 template <typename Mutex> 63 class scoped_lock : private noncopyable 64 { 65 public: 66 typedef Mutex mutex_type; 67 scoped_lock(Mutex & mx,bool initially_locked=true)68 explicit scoped_lock(Mutex& mx, bool initially_locked=true) 69 : m_mutex(mx), m_locked(false) 70 { 71 if (initially_locked) lock(); 72 } ~scoped_lock()73 ~scoped_lock() 74 { 75 if (m_locked) unlock(); 76 } 77 lock()78 void lock() 79 { 80 if (m_locked) throw lock_error(); 81 lock_ops<Mutex>::lock(m_mutex); 82 m_locked = true; 83 } unlock()84 void unlock() 85 { 86 if (!m_locked) throw lock_error(); 87 lock_ops<Mutex>::unlock(m_mutex); 88 m_locked = false; 89 } 90 locked() const91 bool locked() const { return m_locked; } operator const void*() const92 operator const void*() const { return m_locked ? this : 0; } 93 94 private: 95 friend class boost::condition; 96 97 Mutex& m_mutex; 98 bool m_locked; 99 }; 100 101 template <typename TryMutex> 102 class scoped_try_lock : private noncopyable 103 { 104 public: 105 typedef TryMutex mutex_type; 106 scoped_try_lock(TryMutex & mx)107 explicit scoped_try_lock(TryMutex& mx) 108 : m_mutex(mx), m_locked(false) 109 { 110 try_lock(); 111 } scoped_try_lock(TryMutex & mx,bool initially_locked)112 scoped_try_lock(TryMutex& mx, bool initially_locked) 113 : m_mutex(mx), m_locked(false) 114 { 115 if (initially_locked) lock(); 116 } ~scoped_try_lock()117 ~scoped_try_lock() 118 { 119 if (m_locked) unlock(); 120 } 121 lock()122 void lock() 123 { 124 if (m_locked) throw lock_error(); 125 lock_ops<TryMutex>::lock(m_mutex); 126 m_locked = true; 127 } try_lock()128 bool try_lock() 129 { 130 if (m_locked) throw lock_error(); 131 return (m_locked = lock_ops<TryMutex>::trylock(m_mutex)); 132 } unlock()133 void unlock() 134 { 135 if (!m_locked) throw lock_error(); 136 lock_ops<TryMutex>::unlock(m_mutex); 137 m_locked = false; 138 } 139 locked() const140 bool locked() const { return m_locked; } operator const void*() const141 operator const void*() const { return m_locked ? this : 0; } 142 143 private: 144 friend class boost::condition; 145 146 TryMutex& m_mutex; 147 bool m_locked; 148 }; 149 150 template <typename TimedMutex> 151 class scoped_timed_lock : private noncopyable 152 { 153 public: 154 typedef TimedMutex mutex_type; 155 scoped_timed_lock(TimedMutex & mx,const xtime & xt)156 scoped_timed_lock(TimedMutex& mx, const xtime& xt) 157 : m_mutex(mx), m_locked(false) 158 { 159 timed_lock(xt); 160 } scoped_timed_lock(TimedMutex & mx,bool initially_locked)161 scoped_timed_lock(TimedMutex& mx, bool initially_locked) 162 : m_mutex(mx), m_locked(false) 163 { 164 if (initially_locked) lock(); 165 } ~scoped_timed_lock()166 ~scoped_timed_lock() 167 { 168 if (m_locked) unlock(); 169 } 170 lock()171 void lock() 172 { 173 if (m_locked) throw lock_error(); 174 lock_ops<TimedMutex>::lock(m_mutex); 175 m_locked = true; 176 } try_lock()177 bool try_lock() 178 { 179 if (m_locked) throw lock_error(); 180 return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex)); 181 } timed_lock(const xtime & xt)182 bool timed_lock(const xtime& xt) 183 { 184 if (m_locked) throw lock_error(); 185 return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt)); 186 } unlock()187 void unlock() 188 { 189 if (!m_locked) throw lock_error(); 190 lock_ops<TimedMutex>::unlock(m_mutex); 191 m_locked = false; 192 } 193 locked() const194 bool locked() const { return m_locked; } operator const void*() const195 operator const void*() const { return m_locked ? this : 0; } 196 197 private: 198 friend class boost::condition; 199 200 TimedMutex& m_mutex; 201 bool m_locked; 202 }; 203 204 } // namespace thread 205 } // namespace detail 206 } // namespace boost 207 208 #endif // BOOST_XLOCK_WEK070601_HPP 209 210 // Change Log: 211 // 8 Feb 01 WEKEMPF Initial version. 212 // 22 May 01 WEKEMPF Modified to use xtime for time outs. 213 // 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed 214 // some types. Added locked() methods. 215