1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/ReentrantMonitor.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,267 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: sw=4 ts=4 et : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_ReentrantMonitor_h 1.11 +#define mozilla_ReentrantMonitor_h 1.12 + 1.13 +#include "prmon.h" 1.14 + 1.15 +#ifdef MOZILLA_INTERNAL_API 1.16 +#include "GeckoProfiler.h" 1.17 +#endif //MOZILLA_INTERNAL_API 1.18 + 1.19 +#include "mozilla/BlockingResourceBase.h" 1.20 + 1.21 +// 1.22 +// Provides: 1.23 +// 1.24 +// - ReentrantMonitor, a Java-like monitor 1.25 +// - ReentrantMonitorAutoEnter, an RAII class for ensuring that 1.26 +// ReentrantMonitors are properly entered and exited 1.27 +// 1.28 +// Using ReentrantMonitorAutoEnter is MUCH preferred to making bare calls to 1.29 +// ReentrantMonitor.Enter and Exit. 1.30 +// 1.31 +namespace mozilla { 1.32 + 1.33 + 1.34 +/** 1.35 + * ReentrantMonitor 1.36 + * Java-like monitor. 1.37 + * When possible, use ReentrantMonitorAutoEnter to hold this monitor within a 1.38 + * scope, instead of calling Enter/Exit directly. 1.39 + **/ 1.40 +class NS_COM_GLUE ReentrantMonitor : BlockingResourceBase 1.41 +{ 1.42 +public: 1.43 + /** 1.44 + * ReentrantMonitor 1.45 + * @param aName A name which can reference this monitor 1.46 + */ 1.47 + ReentrantMonitor(const char* aName) : 1.48 + BlockingResourceBase(aName, eReentrantMonitor) 1.49 +#ifdef DEBUG 1.50 + , mEntryCount(0) 1.51 +#endif 1.52 + { 1.53 + MOZ_COUNT_CTOR(ReentrantMonitor); 1.54 + mReentrantMonitor = PR_NewMonitor(); 1.55 + if (!mReentrantMonitor) 1.56 + NS_RUNTIMEABORT("Can't allocate mozilla::ReentrantMonitor"); 1.57 + } 1.58 + 1.59 + /** 1.60 + * ~ReentrantMonitor 1.61 + **/ 1.62 + ~ReentrantMonitor() 1.63 + { 1.64 + NS_ASSERTION(mReentrantMonitor, 1.65 + "improperly constructed ReentrantMonitor or double free"); 1.66 + PR_DestroyMonitor(mReentrantMonitor); 1.67 + mReentrantMonitor = 0; 1.68 + MOZ_COUNT_DTOR(ReentrantMonitor); 1.69 + } 1.70 + 1.71 +#ifndef DEBUG 1.72 + /** 1.73 + * Enter 1.74 + * @see prmon.h 1.75 + **/ 1.76 + void Enter() 1.77 + { 1.78 + PR_EnterMonitor(mReentrantMonitor); 1.79 + } 1.80 + 1.81 + /** 1.82 + * Exit 1.83 + * @see prmon.h 1.84 + **/ 1.85 + void Exit() 1.86 + { 1.87 + PR_ExitMonitor(mReentrantMonitor); 1.88 + } 1.89 + 1.90 + /** 1.91 + * Wait 1.92 + * @see prmon.h 1.93 + **/ 1.94 + nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) 1.95 + { 1.96 +#ifdef MOZILLA_INTERNAL_API 1.97 + GeckoProfilerSleepRAII profiler_sleep; 1.98 +#endif //MOZILLA_INTERNAL_API 1.99 + return PR_Wait(mReentrantMonitor, interval) == PR_SUCCESS ? 1.100 + NS_OK : NS_ERROR_FAILURE; 1.101 + } 1.102 + 1.103 +#else // ifndef DEBUG 1.104 + void Enter(); 1.105 + void Exit(); 1.106 + nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT); 1.107 + 1.108 +#endif // ifndef DEBUG 1.109 + 1.110 + /** 1.111 + * Notify 1.112 + * @see prmon.h 1.113 + **/ 1.114 + nsresult Notify() 1.115 + { 1.116 + return PR_Notify(mReentrantMonitor) == PR_SUCCESS 1.117 + ? NS_OK : NS_ERROR_FAILURE; 1.118 + } 1.119 + 1.120 + /** 1.121 + * NotifyAll 1.122 + * @see prmon.h 1.123 + **/ 1.124 + nsresult NotifyAll() 1.125 + { 1.126 + return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS 1.127 + ? NS_OK : NS_ERROR_FAILURE; 1.128 + } 1.129 + 1.130 +#ifdef DEBUG 1.131 + /** 1.132 + * AssertCurrentThreadIn 1.133 + * @see prmon.h 1.134 + **/ 1.135 + void AssertCurrentThreadIn() 1.136 + { 1.137 + PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor); 1.138 + } 1.139 + 1.140 + /** 1.141 + * AssertNotCurrentThreadIn 1.142 + * @see prmon.h 1.143 + **/ 1.144 + void AssertNotCurrentThreadIn() 1.145 + { 1.146 + // FIXME bug 476536 1.147 + } 1.148 + 1.149 +#else 1.150 + void AssertCurrentThreadIn() 1.151 + { 1.152 + } 1.153 + void AssertNotCurrentThreadIn() 1.154 + { 1.155 + } 1.156 + 1.157 +#endif // ifdef DEBUG 1.158 + 1.159 +private: 1.160 + ReentrantMonitor(); 1.161 + ReentrantMonitor(const ReentrantMonitor&); 1.162 + ReentrantMonitor& operator =(const ReentrantMonitor&); 1.163 + 1.164 + PRMonitor* mReentrantMonitor; 1.165 +#ifdef DEBUG 1.166 + int32_t mEntryCount; 1.167 +#endif 1.168 +}; 1.169 + 1.170 + 1.171 +/** 1.172 + * ReentrantMonitorAutoEnter 1.173 + * Enters the ReentrantMonitor when it enters scope, and exits it when 1.174 + * it leaves scope. 1.175 + * 1.176 + * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit. 1.177 + */ 1.178 +class NS_COM_GLUE MOZ_STACK_CLASS ReentrantMonitorAutoEnter 1.179 +{ 1.180 +public: 1.181 + /** 1.182 + * Constructor 1.183 + * The constructor aquires the given lock. The destructor 1.184 + * releases the lock. 1.185 + * 1.186 + * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. 1.187 + **/ 1.188 + ReentrantMonitorAutoEnter(mozilla::ReentrantMonitor &aReentrantMonitor) : 1.189 + mReentrantMonitor(&aReentrantMonitor) 1.190 + { 1.191 + NS_ASSERTION(mReentrantMonitor, "null monitor"); 1.192 + mReentrantMonitor->Enter(); 1.193 + } 1.194 + 1.195 + ~ReentrantMonitorAutoEnter(void) 1.196 + { 1.197 + mReentrantMonitor->Exit(); 1.198 + } 1.199 + 1.200 + nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) 1.201 + { 1.202 + return mReentrantMonitor->Wait(interval); 1.203 + } 1.204 + 1.205 + nsresult Notify() 1.206 + { 1.207 + return mReentrantMonitor->Notify(); 1.208 + } 1.209 + 1.210 + nsresult NotifyAll() 1.211 + { 1.212 + return mReentrantMonitor->NotifyAll(); 1.213 + } 1.214 + 1.215 +private: 1.216 + ReentrantMonitorAutoEnter(); 1.217 + ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&); 1.218 + ReentrantMonitorAutoEnter& operator =(const ReentrantMonitorAutoEnter&); 1.219 + static void* operator new(size_t) CPP_THROW_NEW; 1.220 + static void operator delete(void*); 1.221 + 1.222 + mozilla::ReentrantMonitor* mReentrantMonitor; 1.223 +}; 1.224 + 1.225 +/** 1.226 + * ReentrantMonitorAutoExit 1.227 + * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves 1.228 + * scope. 1.229 + * 1.230 + * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter. 1.231 + */ 1.232 +class MOZ_STACK_CLASS ReentrantMonitorAutoExit 1.233 +{ 1.234 +public: 1.235 + /** 1.236 + * Constructor 1.237 + * The constructor releases the given lock. The destructor 1.238 + * acquires the lock. The lock must be held before constructing 1.239 + * this object! 1.240 + * 1.241 + * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It 1.242 + * must be already locked. 1.243 + **/ 1.244 + ReentrantMonitorAutoExit(ReentrantMonitor& aReentrantMonitor) : 1.245 + mReentrantMonitor(&aReentrantMonitor) 1.246 + { 1.247 + NS_ASSERTION(mReentrantMonitor, "null monitor"); 1.248 + mReentrantMonitor->AssertCurrentThreadIn(); 1.249 + mReentrantMonitor->Exit(); 1.250 + } 1.251 + 1.252 + ~ReentrantMonitorAutoExit(void) 1.253 + { 1.254 + mReentrantMonitor->Enter(); 1.255 + } 1.256 + 1.257 +private: 1.258 + ReentrantMonitorAutoExit(); 1.259 + ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&); 1.260 + ReentrantMonitorAutoExit& operator =(const ReentrantMonitorAutoExit&); 1.261 + static void* operator new(size_t) CPP_THROW_NEW; 1.262 + static void operator delete(void*); 1.263 + 1.264 + ReentrantMonitor* mReentrantMonitor; 1.265 +}; 1.266 + 1.267 +} // namespace mozilla 1.268 + 1.269 + 1.270 +#endif // ifndef mozilla_ReentrantMonitor_h