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