/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #ifndef _SALHELPER_MONITOR_HXX_ #define _SALHELPER_MONITOR_HXX_ #include #include #include #include #include #include #include #include namespace salhelper { //---------------------------------------------------------------------------- #ifndef SALHELPER_COPYCTOR_API #define SALHELPER_COPYCTOR_API(C) C (const C&); C& operator= (const C&) #endif //---------------------------------------------------------------------------- class MonitorCondition : protected osl::Condition { /** Representation. */ oslInterlockedCount m_nReferenceCount; /** Not implemented. */ SALHELPER_COPYCTOR_API(MonitorCondition); public: /** Construction. */ inline MonitorCondition() SAL_THROW(()) : m_nReferenceCount (0) { Condition::set(); } /** Destruction. */ inline ~MonitorCondition() SAL_THROW(()) { OSL_ASSERT(m_nReferenceCount == 0); } /** Acquire or enter the monitor. */ inline void acquire() SAL_THROW(()) { if (osl_incrementInterlockedCount (&m_nReferenceCount) == 1) { Condition::reset(); } } /** Release or leave the monitor. */ inline void release() SAL_THROW(()) { if (osl_decrementInterlockedCount (&m_nReferenceCount) == 0) { Condition::set(); } } /** Wait until all references are released. */ inline void wait() SAL_THROW(()) { Condition::wait(); } }; //---------------------------------------------------------------------------- class QueuedReaderWriterMonitor : public salhelper::ReferenceObject { /** Representation. */ typedef salhelper::Future future_type; salhelper::FutureQueue m_aQueue; salhelper::MonitorCondition m_aMonitor; /** Not implemented. */ SALHELPER_COPYCTOR_API(QueuedReaderWriterMonitor); public: /** Construction. */ inline QueuedReaderWriterMonitor() { // Insert the token. m_aQueue.put(0); } /** Acquire read access. */ inline void acquireReader() { // Obtain the token. rtl::Reference xFuture (m_aQueue.get()); xFuture->get(); // Enter the monitor. m_aMonitor.acquire(); // Push back the token. m_aQueue.put(0); } /** Release read access. */ inline void releaseReader() { // Leave the monitor. m_aMonitor.release(); } /** Acquire write access. */ inline void acquireWriter() { // Obtain the token. rtl::Reference xFuture (m_aQueue.get()); xFuture->get(); // Wait until all readers have left. m_aMonitor.wait(); } /** Release write access. */ inline void releaseWriter() { // Push back the token. m_aQueue.put(0); } protected: /** Destruction. */ virtual ~QueuedReaderWriterMonitor() {} }; //---------------------------------------------------------------------------- template class ReaderGuard { /** Representation. */ monitor_type *m_pMonitor; /** Not implemented. */ SALHELPER_COPYCTOR_API(ReaderGuard); public: /** Construction. Acquire monitor read access. */ inline ReaderGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor) { m_pMonitor->acquireReader(); } /** Construction. Acquire monitor read access. */ inline ReaderGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor) { OSL_PRECOND(m_pMonitor, "ReaderGuard::ReaderGuard(): No Monitor"); m_pMonitor->acquireReader(); } /** Destruction. Release monitor read access. */ inline ~ReaderGuard() { if (m_pMonitor) m_pMonitor->releaseReader(); } /** Release monitor read access. */ inline void clear() { if (m_pMonitor) { m_pMonitor->releaseReader(); m_pMonitor = 0; } } }; //---------------------------------------------------------------------------- typedef ReaderGuard QueuedReaderGuard; //---------------------------------------------------------------------------- template class WriterGuard { /** Representation. */ monitor_type *m_pMonitor; /** Not implemented. */ SALHELPER_COPYCTOR_API(WriterGuard); public: /** Construction. Acquire monitor write access. */ inline WriterGuard (monitor_type & rMonitor) : m_pMonitor (&rMonitor) { m_pMonitor->acquireWriter(); } /** Construction. Acquire monitor write access. */ inline WriterGuard (monitor_type * pMonitor) : m_pMonitor (pMonitor) { OSL_PRECOND(m_pMonitor, "WriterGuard::WriterGuard(): No Monitor"); m_pMonitor->acquireWriter(); } /** Destruction. Release monitor write access. */ inline ~WriterGuard() { if (m_pMonitor) m_pMonitor->releaseWriter(); } /** Release monitor write access. */ inline void clear() { if (m_pMonitor) { m_pMonitor->releaseWriter(); m_pMonitor = 0; } } }; //---------------------------------------------------------------------------- typedef WriterGuard QueuedWriterGuard; //---------------------------------------------------------------------------- } // namespace salhelper #endif /* !_SALHELPER_MONITOR_HXX_ */