xref: /AOO42X/main/salhelper/inc/salhelper/monitor.hxx (revision 9bce9b0d387299c68bd81d539e1478357a103de5)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _SALHELPER_MONITOR_HXX_
25 #define _SALHELPER_MONITOR_HXX_
26 
27 #include <sal/types.h>
28 #include <osl/conditn.hxx>
29 #include <osl/diagnose.h>
30 #include <osl/interlck.h>
31 #include <rtl/ref.hxx>
32 #include <salhelper/refobj.hxx>
33 #include <salhelper/future.hxx>
34 #include <salhelper/futurequeue.hxx>
35 
36 namespace salhelper
37 {
38 
39 //----------------------------------------------------------------------------
40 
41 #ifndef SALHELPER_COPYCTOR_API
42 #define SALHELPER_COPYCTOR_API(C) C (const C&); C& operator= (const C&)
43 #endif
44 
45 //----------------------------------------------------------------------------
46 
47 class MonitorCondition : protected osl::Condition
48 {
49     /** Representation.
50      */
51     oslInterlockedCount m_nReferenceCount;
52 
53     /** Not implemented.
54      */
55     SALHELPER_COPYCTOR_API(MonitorCondition);
56 
57 public:
58     /** Construction.
59      */
60     inline MonitorCondition() SAL_THROW(()) : m_nReferenceCount (0)
61     {
62         Condition::set();
63     }
64 
65     /** Destruction.
66      */
67     inline ~MonitorCondition() SAL_THROW(())
68     {
69         OSL_ASSERT(m_nReferenceCount == 0);
70     }
71 
72     /** Acquire or enter the monitor.
73      */
acquire()74     inline void acquire() SAL_THROW(())
75     {
76         if (osl_incrementInterlockedCount (&m_nReferenceCount) == 1)
77         {
78             Condition::reset();
79         }
80     }
81 
82     /** Release or leave the monitor.
83      */
release()84     inline void release() SAL_THROW(())
85     {
86         if (osl_decrementInterlockedCount (&m_nReferenceCount) == 0)
87         {
88             Condition::set();
89         }
90     }
91 
92     /** Wait until all references are released.
93      */
wait()94     inline void wait() SAL_THROW(())
95     {
96         Condition::wait();
97     }
98 };
99 
100 //----------------------------------------------------------------------------
101 
102 class QueuedReaderWriterMonitor : public salhelper::ReferenceObject
103 {
104     /** Representation.
105      */
106     typedef salhelper::Future<sal_Int32> future_type;
107 
108     salhelper::FutureQueue<sal_Int32> m_aQueue;
109     salhelper::MonitorCondition       m_aMonitor;
110 
111     /** Not implemented.
112      */
113     SALHELPER_COPYCTOR_API(QueuedReaderWriterMonitor);
114 
115 public:
116     /** Construction.
117      */
QueuedReaderWriterMonitor()118     inline QueuedReaderWriterMonitor()
119     {
120         // Insert the token.
121         m_aQueue.put(0);
122     }
123 
124     /** Acquire read access.
125      */
acquireReader()126     inline void acquireReader()
127     {
128         // Obtain the token.
129         rtl::Reference<future_type> xFuture (m_aQueue.get());
130         xFuture->get();
131 
132         // Enter the monitor.
133         m_aMonitor.acquire();
134 
135         // Push back the token.
136         m_aQueue.put(0);
137     }
138 
139     /** Release read access.
140      */
releaseReader()141     inline void releaseReader()
142     {
143         // Leave the monitor.
144         m_aMonitor.release();
145     }
146 
147     /** Acquire write access.
148      */
acquireWriter()149     inline void acquireWriter()
150     {
151         // Obtain the token.
152         rtl::Reference<future_type> xFuture (m_aQueue.get());
153         xFuture->get();
154 
155         // Wait until all readers have left.
156         m_aMonitor.wait();
157     }
158 
159     /** Release write access.
160      */
releaseWriter()161     inline void releaseWriter()
162     {
163         // Push back the token.
164         m_aQueue.put(0);
165     }
166 
167 protected:
168     /** Destruction.
169      */
~QueuedReaderWriterMonitor()170     virtual ~QueuedReaderWriterMonitor()
171     {}
172 };
173 
174 //----------------------------------------------------------------------------
175 
176 template<class monitor_type>
177 class ReaderGuard
178 {
179     /** Representation.
180      */
181     monitor_type *m_pMonitor;
182 
183     /** Not implemented.
184      */
185     SALHELPER_COPYCTOR_API(ReaderGuard<monitor_type>);
186 
187 public:
188     /** Construction. Acquire monitor read access.
189      */
ReaderGuard(monitor_type & rMonitor)190     inline ReaderGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor)
191     {
192         m_pMonitor->acquireReader();
193     }
194 
195     /** Construction. Acquire monitor read access.
196      */
ReaderGuard(monitor_type * pMonitor)197     inline ReaderGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor)
198     {
199         OSL_PRECOND(m_pMonitor, "ReaderGuard::ReaderGuard(): No Monitor");
200         m_pMonitor->acquireReader();
201     }
202 
203     /** Destruction. Release monitor read access.
204      */
~ReaderGuard()205     inline ~ReaderGuard()
206     {
207         if (m_pMonitor)
208             m_pMonitor->releaseReader();
209     }
210 
211     /** Release monitor read access.
212      */
clear()213     inline void clear()
214     {
215         if (m_pMonitor)
216         {
217             m_pMonitor->releaseReader();
218             m_pMonitor = 0;
219         }
220     }
221 };
222 
223 //----------------------------------------------------------------------------
224 
225 typedef ReaderGuard<QueuedReaderWriterMonitor> QueuedReaderGuard;
226 
227 //----------------------------------------------------------------------------
228 
229 template<class monitor_type>
230 class WriterGuard
231 {
232     /** Representation.
233      */
234     monitor_type *m_pMonitor;
235 
236     /** Not implemented.
237      */
238     SALHELPER_COPYCTOR_API(WriterGuard<monitor_type>);
239 
240 public:
241     /** Construction. Acquire monitor write access.
242      */
WriterGuard(monitor_type & rMonitor)243     inline WriterGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor)
244     {
245         m_pMonitor->acquireWriter();
246     }
247 
248     /** Construction. Acquire monitor write access.
249      */
WriterGuard(monitor_type * pMonitor)250     inline WriterGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor)
251     {
252         OSL_PRECOND(m_pMonitor, "WriterGuard::WriterGuard(): No Monitor");
253         m_pMonitor->acquireWriter();
254     }
255 
256     /** Destruction. Release monitor write access.
257      */
~WriterGuard()258     inline ~WriterGuard()
259     {
260         if (m_pMonitor)
261             m_pMonitor->releaseWriter();
262     }
263 
264     /** Release monitor write access.
265      */
clear()266     inline void clear()
267     {
268         if (m_pMonitor)
269         {
270             m_pMonitor->releaseWriter();
271             m_pMonitor = 0;
272         }
273     }
274 };
275 
276 //----------------------------------------------------------------------------
277 
278 typedef WriterGuard<QueuedReaderWriterMonitor> QueuedWriterGuard;
279 
280 //----------------------------------------------------------------------------
281 
282 } // namespace salhelper
283 
284 #endif /* !_SALHELPER_MONITOR_HXX_ */
285