UDK 3.2.7 C/C++ API Reference
salhelper/monitor.hxx
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /*************************************************************************
00003  *
00004  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
00005  *
00006  * Copyright 2000, 2010 Oracle and/or its affiliates.
00007  *
00008  * OpenOffice.org - a multi-platform office productivity suite
00009  *
00010  * This file is part of OpenOffice.org.
00011  *
00012  * OpenOffice.org is free software: you can redistribute it and/or modify
00013  * it under the terms of the GNU Lesser General Public License version 3
00014  * only, as published by the Free Software Foundation.
00015  *
00016  * OpenOffice.org is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Lesser General Public License version 3 for more details
00020  * (a copy is included in the LICENSE file that accompanied this code).
00021  *
00022  * You should have received a copy of the GNU Lesser General Public License
00023  * version 3 along with OpenOffice.org.  If not, see
00024  * <http://www.openoffice.org/license.html>
00025  * for a copy of the LGPLv3 License.
00026  *
00027  ************************************************************************/
00028 
00029 #ifndef _SALHELPER_MONITOR_HXX_
00030 #define _SALHELPER_MONITOR_HXX_
00031 
00032 #include <sal/types.h>
00033 #include <osl/conditn.hxx>
00034 #include <osl/diagnose.h>
00035 #include <osl/interlck.h>
00036 #include <rtl/ref.hxx>
00037 #include <salhelper/refobj.hxx>
00038 #include <salhelper/future.hxx>
00039 #include <salhelper/futurequeue.hxx>
00040 
00041 namespace salhelper
00042 {
00043 
00044 //----------------------------------------------------------------------------
00045 
00046 #ifndef SALHELPER_COPYCTOR_API
00047 #define SALHELPER_COPYCTOR_API(C) C (const C&); C& operator= (const C&)
00048 #endif
00049 
00050 //----------------------------------------------------------------------------
00051 
00052 class MonitorCondition : protected osl::Condition
00053 {
00056     oslInterlockedCount m_nReferenceCount;
00057 
00060     SALHELPER_COPYCTOR_API(MonitorCondition);
00061 
00062 public:
00065     inline MonitorCondition() SAL_THROW(()) : m_nReferenceCount (0)
00066     {
00067         Condition::set();
00068     }
00069 
00072     inline ~MonitorCondition() SAL_THROW(())
00073     {
00074         OSL_ASSERT(m_nReferenceCount == 0);
00075     }
00076 
00079     inline void acquire() SAL_THROW(())
00080     {
00081         if (osl_incrementInterlockedCount (&m_nReferenceCount) == 1)
00082         {
00083             Condition::reset();
00084         }
00085     }
00086 
00089     inline void release() SAL_THROW(())
00090     {
00091         if (osl_decrementInterlockedCount (&m_nReferenceCount) == 0)
00092         {
00093             Condition::set();
00094         }
00095     }
00096 
00099     inline void wait() SAL_THROW(())
00100     {
00101         Condition::wait();
00102     }
00103 };
00104 
00105 //----------------------------------------------------------------------------
00106 
00107 class QueuedReaderWriterMonitor : public salhelper::ReferenceObject
00108 {
00111     typedef salhelper::Future<sal_Int32> future_type;
00112 
00113     salhelper::FutureQueue<sal_Int32> m_aQueue;
00114     salhelper::MonitorCondition       m_aMonitor;
00115 
00118     SALHELPER_COPYCTOR_API(QueuedReaderWriterMonitor);
00119 
00120 public:
00123     inline QueuedReaderWriterMonitor()
00124     {
00125         // Insert the token.
00126         m_aQueue.put(0);
00127     }
00128 
00131     inline void acquireReader()
00132     {
00133         // Obtain the token.
00134         rtl::Reference<future_type> xFuture (m_aQueue.get());
00135         xFuture->get();
00136 
00137         // Enter the monitor.
00138         m_aMonitor.acquire();
00139 
00140         // Push back the token.
00141         m_aQueue.put(0);
00142     }
00143 
00146     inline void releaseReader()
00147     {
00148         // Leave the monitor.
00149         m_aMonitor.release();
00150     }
00151 
00154     inline void acquireWriter()
00155     {
00156         // Obtain the token.
00157         rtl::Reference<future_type> xFuture (m_aQueue.get());
00158         xFuture->get();
00159 
00160         // Wait until all readers have left.
00161         m_aMonitor.wait();
00162     }
00163 
00166     inline void releaseWriter()
00167     {
00168         // Push back the token.
00169         m_aQueue.put(0);
00170     }
00171 
00172 protected:
00175     virtual ~QueuedReaderWriterMonitor()
00176     {}
00177 };
00178 
00179 //----------------------------------------------------------------------------
00180 
00181 template<class monitor_type>
00182 class ReaderGuard
00183 {
00186     monitor_type *m_pMonitor;
00187 
00190     SALHELPER_COPYCTOR_API(ReaderGuard<monitor_type>);
00191 
00192 public:
00195     inline ReaderGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor)
00196     {
00197         m_pMonitor->acquireReader();
00198     }
00199 
00202     inline ReaderGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor)
00203     {
00204         OSL_PRECOND(m_pMonitor, "ReaderGuard::ReaderGuard(): No Monitor");
00205         m_pMonitor->acquireReader();
00206     }
00207 
00210     inline ~ReaderGuard()
00211     {
00212         if (m_pMonitor)
00213             m_pMonitor->releaseReader();
00214     }
00215 
00218     inline void clear()
00219     {
00220         if (m_pMonitor)
00221         {
00222             m_pMonitor->releaseReader();
00223             m_pMonitor = 0;
00224         }
00225     }
00226 };
00227 
00228 //----------------------------------------------------------------------------
00229 
00230 typedef ReaderGuard<QueuedReaderWriterMonitor> QueuedReaderGuard;
00231 
00232 //----------------------------------------------------------------------------
00233 
00234 template<class monitor_type>
00235 class WriterGuard
00236 {
00239     monitor_type *m_pMonitor;
00240 
00243     SALHELPER_COPYCTOR_API(WriterGuard<monitor_type>);
00244 
00245 public:
00248     inline WriterGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor)
00249     {
00250         m_pMonitor->acquireWriter();
00251     }
00252 
00255     inline WriterGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor)
00256     {
00257         OSL_PRECOND(m_pMonitor, "WriterGuard::WriterGuard(): No Monitor");
00258         m_pMonitor->acquireWriter();
00259     }
00260 
00263     inline ~WriterGuard()
00264     {
00265         if (m_pMonitor)
00266             m_pMonitor->releaseWriter();
00267     }
00268 
00271     inline void clear()
00272     {
00273         if (m_pMonitor)
00274         {
00275             m_pMonitor->releaseWriter();
00276             m_pMonitor = 0;
00277         }
00278     }
00279 };
00280 
00281 //----------------------------------------------------------------------------
00282 
00283 typedef WriterGuard<QueuedReaderWriterMonitor> QueuedWriterGuard;
00284 
00285 //----------------------------------------------------------------------------
00286 
00287 } // namespace salhelper
00288 
00289 #endif /* !_SALHELPER_MONITOR_HXX_ */
00290 
00291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines