libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_THREAD_TOKEN_MUTEX_H__ 00029 #define MOOST_THREAD_TOKEN_MUTEX_H__ 00030 00031 #include <set> 00032 #include <boost/thread/condition.hpp> 00033 #include <boost/thread/mutex.hpp> 00034 00035 namespace moost { namespace thread { 00036 00041 template<typename T> 00042 class token_mutex 00043 { 00044 private: 00045 00046 boost::mutex m_mutex; 00047 boost::condition m_cond; 00048 std::set<T> m_tokens; 00049 bool m_full_lock; 00050 00051 public: 00052 class scoped_promote_lock; 00053 00057 class scoped_lock 00058 { 00059 private: 00060 token_mutex<T>& m_token_mutex; 00061 T m_token; 00062 00063 friend class scoped_promote_lock; 00064 public: 00065 scoped_lock( token_mutex<T> & token_mutex, 00066 const T & token ) 00067 : m_token_mutex(token_mutex), 00068 m_token(token) 00069 { 00070 m_token_mutex.lock(m_token); 00071 } 00072 ~scoped_lock() 00073 { 00074 m_token_mutex.unlock(m_token); 00075 } 00076 }; 00077 00081 class scoped_try_lock 00082 { 00083 private: 00084 token_mutex<T>& m_token_mutex; 00085 T m_token; 00086 bool m_got_lock; 00087 public: 00088 scoped_try_lock( token_mutex<T> & token_mutex, 00089 const T & token ) 00090 : m_token_mutex(token_mutex), 00091 m_token(token) 00092 { 00093 m_got_lock = m_token_mutex.trylock(m_token); 00094 } 00095 operator bool () const { return m_got_lock; } 00096 bool operator ! () const { return !m_got_lock; } 00097 ~scoped_try_lock() 00098 { 00099 if (m_got_lock) 00100 m_token_mutex.unlock(m_token); 00101 } 00102 }; 00103 00107 class scoped_full_lock 00108 { 00109 private: 00110 token_mutex<T>& m_token_mutex; 00111 public: 00112 scoped_full_lock(token_mutex<T> & token_mutex) 00113 : m_token_mutex(token_mutex) 00114 { 00115 m_token_mutex.full_lock(); 00116 } 00117 ~scoped_full_lock() 00118 { 00119 m_token_mutex.full_unlock(); 00120 } 00121 }; 00122 00126 class scoped_promote_lock 00127 { 00128 private: 00129 token_mutex<T>& m_token_mutex; 00130 public: 00131 scoped_promote_lock(scoped_lock& lock) 00132 : m_token_mutex(lock.m_token_mutex) 00133 { 00134 m_token_mutex.unlock(lock.m_token); 00135 m_token_mutex.full_lock(); 00136 } 00137 00138 ~scoped_promote_lock() 00139 { 00140 m_token_mutex.full_unlock(); 00141 } 00142 }; 00143 00147 token_mutex() : m_full_lock(false) {} 00148 00152 void lock(const T& token) 00153 { 00154 boost::mutex::scoped_lock lock(m_mutex); 00155 while (m_tokens.find(token) != m_tokens.end() || m_full_lock) 00156 m_cond.wait(lock); 00157 m_tokens.insert(token); 00158 } 00159 00163 void unlock(const T& token) 00164 { 00165 boost::mutex::scoped_lock lock(m_mutex); 00166 m_tokens.erase(token); 00167 m_cond.notify_all(); 00168 } 00169 00173 void full_lock() 00174 { 00175 boost::mutex::scoped_lock lock(m_mutex); 00176 m_full_lock = true; 00177 while (!m_tokens.empty()) 00178 m_cond.wait(lock); 00179 } 00180 00184 void full_unlock() 00185 { 00186 boost::mutex::scoped_lock lock(m_mutex); 00187 m_full_lock = false; 00188 m_cond.notify_all(); 00189 } 00190 00197 bool trylock(const T& token) 00198 { 00199 boost::mutex::scoped_lock lock(m_mutex); 00200 if (m_tokens.find(token) == m_tokens.end() && !m_full_lock) 00201 { 00202 m_tokens.insert(token); 00203 return true; 00204 } 00205 return false; 00206 } 00207 }; 00208 00209 }} // moost::thread 00210 00211 #endif // MOOST_THREAD_TOKEN_MUTEX_H__