• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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