1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/interprocess for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP 12 #define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 # 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/interprocess/detail/config_begin.hpp> 23 #include <boost/interprocess/detail/workaround.hpp> 24 #include <boost/interprocess/creation_tags.hpp> 25 #include <boost/interprocess/permissions.hpp> 26 #include <boost/interprocess/detail/interprocess_tester.hpp> 27 #include <boost/interprocess/detail/posix_time_types_wrk.hpp> 28 #include <boost/interprocess/sync/windows/named_sync.hpp> 29 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp> 30 #include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp> 31 32 namespace boost { 33 namespace interprocess { 34 namespace ipcdetail { 35 36 class windows_named_condition_any 37 { 38 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 39 40 //Non-copyable 41 windows_named_condition_any(); 42 windows_named_condition_any(const windows_named_condition_any &); 43 windows_named_condition_any &operator=(const windows_named_condition_any &); 44 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 45 46 public: windows_named_condition_any(create_only_t,const char * name,const permissions & perm)47 windows_named_condition_any 48 (create_only_t, const char *name, const permissions &perm) 49 : m_condition_data() 50 { 51 named_cond_callbacks callbacks(m_condition_data.get_members()); 52 m_named_sync.open_or_create(DoCreate, name, perm, callbacks); 53 } 54 windows_named_condition_any(open_or_create_t,const char * name,const permissions & perm)55 windows_named_condition_any 56 (open_or_create_t, const char *name, const permissions &perm) 57 : m_condition_data() 58 { 59 named_cond_callbacks callbacks(m_condition_data.get_members()); 60 m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); 61 } 62 windows_named_condition_any(open_only_t,const char * name)63 windows_named_condition_any(open_only_t, const char *name) 64 : m_condition_data() 65 { 66 named_cond_callbacks callbacks(m_condition_data.get_members()); 67 m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); 68 } 69 ~windows_named_condition_any()70 ~windows_named_condition_any() 71 { 72 named_cond_callbacks callbacks(m_condition_data.get_members()); 73 m_named_sync.close(callbacks); 74 } 75 notify_one()76 void notify_one() 77 { m_condition_data.notify_one(); } 78 notify_all()79 void notify_all() 80 { m_condition_data.notify_all(); } 81 82 template <typename L> timed_wait(L & lock,const boost::posix_time::ptime & abs_time)83 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) 84 { return m_condition_data.timed_wait(lock, abs_time); } 85 86 template <typename L, typename Pr> timed_wait(L & lock,const boost::posix_time::ptime & abs_time,Pr pred)87 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) 88 { return m_condition_data.timed_wait(lock, abs_time, pred); } 89 90 template <typename L> wait(L & lock)91 void wait(L& lock) 92 { m_condition_data.wait(lock); } 93 94 template <typename L, typename Pr> wait(L & lock,Pr pred)95 void wait(L& lock, Pr pred) 96 { m_condition_data.wait(lock, pred); } 97 remove(const char * name)98 static bool remove(const char *name) 99 { return windows_named_sync::remove(name); } 100 101 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 102 private: 103 dont_close_on_destruction()104 void dont_close_on_destruction() 105 {} 106 107 friend class interprocess_tester; 108 109 struct condition_data 110 { 111 typedef boost::int32_t integer_type; 112 typedef winapi_semaphore_wrapper semaphore_type; 113 typedef winapi_mutex_wrapper mutex_type; 114 get_nwaiters_blockedboost::interprocess::ipcdetail::windows_named_condition_any::condition_data115 integer_type &get_nwaiters_blocked() 116 { return m_nwaiters_blocked; } 117 get_nwaiters_goneboost::interprocess::ipcdetail::windows_named_condition_any::condition_data118 integer_type &get_nwaiters_gone() 119 { return m_nwaiters_gone; } 120 get_nwaiters_to_unblockboost::interprocess::ipcdetail::windows_named_condition_any::condition_data121 integer_type &get_nwaiters_to_unblock() 122 { return m_nwaiters_to_unblock; } 123 get_sem_block_queueboost::interprocess::ipcdetail::windows_named_condition_any::condition_data124 semaphore_type &get_sem_block_queue() 125 { return m_sem_block_queue; } 126 get_sem_block_lockboost::interprocess::ipcdetail::windows_named_condition_any::condition_data127 semaphore_type &get_sem_block_lock() 128 { return m_sem_block_lock; } 129 get_mtx_unblock_lockboost::interprocess::ipcdetail::windows_named_condition_any::condition_data130 mutex_type &get_mtx_unblock_lock() 131 { return m_mtx_unblock_lock; } 132 133 integer_type m_nwaiters_blocked; 134 integer_type m_nwaiters_gone; 135 integer_type m_nwaiters_to_unblock; 136 winapi_semaphore_wrapper m_sem_block_queue; 137 winapi_semaphore_wrapper m_sem_block_lock; 138 winapi_mutex_wrapper m_mtx_unblock_lock; 139 }; 140 141 class named_cond_callbacks : public windows_named_sync_interface 142 { 143 typedef __int64 sem_count_t; 144 mutable sem_count_t sem_counts [2]; 145 146 public: named_cond_callbacks(condition_data & cond_data)147 named_cond_callbacks(condition_data &cond_data) 148 : m_condition_data(cond_data) 149 {} 150 get_data_size() const151 virtual std::size_t get_data_size() const 152 { return sizeof(sem_counts); } 153 buffer_with_final_data_to_file()154 virtual const void *buffer_with_final_data_to_file() 155 { 156 sem_counts[0] = m_condition_data.m_sem_block_queue.value(); 157 sem_counts[1] = m_condition_data.m_sem_block_lock.value(); 158 return &sem_counts; 159 } 160 buffer_with_init_data_to_file()161 virtual const void *buffer_with_init_data_to_file() 162 { 163 sem_counts[0] = 0; 164 sem_counts[1] = 1; 165 return &sem_counts; 166 } 167 buffer_to_store_init_data_from_file()168 virtual void *buffer_to_store_init_data_from_file() 169 { return &sem_counts; } 170 open(create_enum_t,const char * id_name)171 virtual bool open(create_enum_t, const char *id_name) 172 { 173 m_condition_data.m_nwaiters_blocked = 0; 174 m_condition_data.m_nwaiters_gone = 0; 175 m_condition_data.m_nwaiters_to_unblock = 0; 176 177 //Now open semaphores and mutex. 178 //Use local variables + swap to guarantee consistent 179 //initialization and cleanup in case any opening fails 180 permissions perm; 181 perm.set_unrestricted(); 182 std::string aux_str = "Global\\bipc.cond."; 183 aux_str += id_name; 184 std::size_t pos = aux_str.size(); 185 186 //sem_block_queue 187 aux_str += "_bq"; 188 winapi_semaphore_wrapper sem_block_queue; 189 bool created; 190 if(!sem_block_queue.open_or_create 191 (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) 192 return false; 193 aux_str.erase(pos); 194 195 //sem_block_lock 196 aux_str += "_bl"; 197 winapi_semaphore_wrapper sem_block_lock; 198 if(!sem_block_lock.open_or_create 199 (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) 200 return false; 201 aux_str.erase(pos); 202 203 //mtx_unblock_lock 204 aux_str += "_ul"; 205 winapi_mutex_wrapper mtx_unblock_lock; 206 if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) 207 return false; 208 209 //All ok, commit data 210 m_condition_data.m_sem_block_queue.swap(sem_block_queue); 211 m_condition_data.m_sem_block_lock.swap(sem_block_lock); 212 m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); 213 return true; 214 } 215 close()216 virtual void close() 217 { 218 m_condition_data.m_sem_block_queue.close(); 219 m_condition_data.m_sem_block_lock.close(); 220 m_condition_data.m_mtx_unblock_lock.close(); 221 m_condition_data.m_nwaiters_blocked = 0; 222 m_condition_data.m_nwaiters_gone = 0; 223 m_condition_data.m_nwaiters_to_unblock = 0; 224 } 225 ~named_cond_callbacks()226 virtual ~named_cond_callbacks() 227 {} 228 229 private: 230 condition_data &m_condition_data; 231 }; 232 233 windows_named_sync m_named_sync; 234 ipcdetail::condition_8a_wrapper<condition_data> m_condition_data; 235 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 236 }; 237 238 } //namespace ipcdetail { 239 } //namespace interprocess { 240 } //namespace boost { 241 242 #include <boost/interprocess/detail/config_end.hpp> 243 244 #endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP 245