Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP Chris@16: #define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: namespace ipcdetail { Chris@16: Chris@16: class windows_named_condition_any Chris@16: { Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: Chris@16: //Non-copyable Chris@16: windows_named_condition_any(); Chris@16: windows_named_condition_any(const windows_named_condition_any &); Chris@16: windows_named_condition_any &operator=(const windows_named_condition_any &); Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: windows_named_condition_any Chris@16: (create_only_t, const char *name, const permissions &perm) Chris@16: : m_condition_data() Chris@16: { Chris@16: named_cond_callbacks callbacks(m_condition_data.get_members()); Chris@16: m_named_sync.open_or_create(DoCreate, name, perm, callbacks); Chris@16: } Chris@16: Chris@16: windows_named_condition_any Chris@16: (open_or_create_t, const char *name, const permissions &perm) Chris@16: : m_condition_data() Chris@16: { Chris@16: named_cond_callbacks callbacks(m_condition_data.get_members()); Chris@16: m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); Chris@16: } Chris@16: Chris@16: windows_named_condition_any(open_only_t, const char *name) Chris@16: : m_condition_data() Chris@16: { Chris@16: named_cond_callbacks callbacks(m_condition_data.get_members()); Chris@16: m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); Chris@16: } Chris@16: Chris@16: ~windows_named_condition_any() Chris@16: { Chris@16: named_cond_callbacks callbacks(m_condition_data.get_members()); Chris@16: m_named_sync.close(callbacks); Chris@16: } Chris@16: Chris@16: void notify_one() Chris@16: { m_condition_data.notify_one(); } Chris@16: Chris@16: void notify_all() Chris@16: { m_condition_data.notify_all(); } Chris@16: Chris@16: template Chris@16: bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) Chris@16: { return m_condition_data.timed_wait(lock, abs_time); } Chris@16: Chris@16: template Chris@16: bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) Chris@16: { return m_condition_data.timed_wait(lock, abs_time, pred); } Chris@16: Chris@16: template Chris@16: void wait(L& lock) Chris@16: { m_condition_data.wait(lock); } Chris@16: Chris@16: template Chris@16: void wait(L& lock, Pr pred) Chris@16: { m_condition_data.wait(lock, pred); } Chris@16: Chris@16: static bool remove(const char *name) Chris@16: { return windows_named_sync::remove(name); } Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: Chris@101: void dont_close_on_destruction() Chris@16: {} Chris@16: Chris@16: friend class interprocess_tester; Chris@16: Chris@16: struct condition_data Chris@16: { Chris@16: typedef boost::int32_t integer_type; Chris@16: typedef winapi_semaphore_wrapper semaphore_type; Chris@16: typedef winapi_mutex_wrapper mutex_type; Chris@16: Chris@16: integer_type &get_nwaiters_blocked() Chris@16: { return m_nwaiters_blocked; } Chris@16: Chris@16: integer_type &get_nwaiters_gone() Chris@16: { return m_nwaiters_gone; } Chris@16: Chris@16: integer_type &get_nwaiters_to_unblock() Chris@16: { return m_nwaiters_to_unblock; } Chris@16: Chris@16: semaphore_type &get_sem_block_queue() Chris@16: { return m_sem_block_queue; } Chris@16: Chris@16: semaphore_type &get_sem_block_lock() Chris@16: { return m_sem_block_lock; } Chris@16: Chris@16: mutex_type &get_mtx_unblock_lock() Chris@16: { return m_mtx_unblock_lock; } Chris@16: Chris@16: integer_type m_nwaiters_blocked; Chris@16: integer_type m_nwaiters_gone; Chris@16: integer_type m_nwaiters_to_unblock; Chris@16: winapi_semaphore_wrapper m_sem_block_queue; Chris@16: winapi_semaphore_wrapper m_sem_block_lock; Chris@16: winapi_mutex_wrapper m_mtx_unblock_lock; Chris@16: }; Chris@16: Chris@16: class named_cond_callbacks : public windows_named_sync_interface Chris@16: { Chris@16: typedef __int64 sem_count_t; Chris@16: mutable sem_count_t sem_counts [2]; Chris@16: Chris@16: public: Chris@16: named_cond_callbacks(condition_data &cond_data) Chris@16: : m_condition_data(cond_data) Chris@16: {} Chris@16: Chris@16: virtual std::size_t get_data_size() const Chris@16: { return sizeof(sem_counts); } Chris@16: Chris@16: virtual const void *buffer_with_final_data_to_file() Chris@16: { Chris@16: sem_counts[0] = m_condition_data.m_sem_block_queue.value(); Chris@16: sem_counts[1] = m_condition_data.m_sem_block_lock.value(); Chris@16: return &sem_counts; Chris@16: } Chris@16: Chris@16: virtual const void *buffer_with_init_data_to_file() Chris@16: { Chris@16: sem_counts[0] = 0; Chris@16: sem_counts[1] = 1; Chris@16: return &sem_counts; Chris@16: } Chris@16: Chris@16: virtual void *buffer_to_store_init_data_from_file() Chris@16: { return &sem_counts; } Chris@16: Chris@16: virtual bool open(create_enum_t, const char *id_name) Chris@16: { Chris@16: m_condition_data.m_nwaiters_blocked = 0; Chris@16: m_condition_data.m_nwaiters_gone = 0; Chris@16: m_condition_data.m_nwaiters_to_unblock = 0; Chris@16: Chris@16: //Now open semaphores and mutex. Chris@16: //Use local variables + swap to guarantee consistent Chris@16: //initialization and cleanup in case any opening fails Chris@16: permissions perm; Chris@16: perm.set_unrestricted(); Chris@16: std::string aux_str = "Global\\bipc.cond."; Chris@16: aux_str += id_name; Chris@16: std::size_t pos = aux_str.size(); Chris@16: Chris@16: //sem_block_queue Chris@16: aux_str += "_bq"; Chris@16: winapi_semaphore_wrapper sem_block_queue; Chris@16: bool created; Chris@16: if(!sem_block_queue.open_or_create Chris@16: (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) Chris@16: return false; Chris@16: aux_str.erase(pos); Chris@16: Chris@16: //sem_block_lock Chris@16: aux_str += "_bl"; Chris@16: winapi_semaphore_wrapper sem_block_lock; Chris@16: if(!sem_block_lock.open_or_create Chris@16: (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) Chris@16: return false; Chris@16: aux_str.erase(pos); Chris@16: Chris@16: //mtx_unblock_lock Chris@16: aux_str += "_ul"; Chris@16: winapi_mutex_wrapper mtx_unblock_lock; Chris@16: if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) Chris@16: return false; Chris@16: Chris@16: //All ok, commit data Chris@16: m_condition_data.m_sem_block_queue.swap(sem_block_queue); Chris@16: m_condition_data.m_sem_block_lock.swap(sem_block_lock); Chris@16: m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); Chris@16: return true; Chris@16: } Chris@16: Chris@16: virtual void close() Chris@16: { Chris@16: m_condition_data.m_sem_block_queue.close(); Chris@16: m_condition_data.m_sem_block_lock.close(); Chris@16: m_condition_data.m_mtx_unblock_lock.close(); Chris@16: m_condition_data.m_nwaiters_blocked = 0; Chris@16: m_condition_data.m_nwaiters_gone = 0; Chris@16: m_condition_data.m_nwaiters_to_unblock = 0; Chris@16: } Chris@16: Chris@16: virtual ~named_cond_callbacks() Chris@16: {} Chris@16: Chris@16: private: Chris@16: condition_data &m_condition_data; Chris@16: }; Chris@16: Chris@16: windows_named_sync m_named_sync; Chris@101: ipcdetail::condition_8a_wrapper m_condition_data; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@16: } //namespace ipcdetail { Chris@16: } //namespace interprocess { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP