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