1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/base/ClearOnShutdown.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,108 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et ft=cpp : */ 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_ClearOnShutdown_h 1.11 +#define mozilla_ClearOnShutdown_h 1.12 + 1.13 +#include "mozilla/LinkedList.h" 1.14 +#include "mozilla/StaticPtr.h" 1.15 +#include "MainThreadUtils.h" 1.16 + 1.17 +/* 1.18 + * This header exports one public method in the mozilla namespace: 1.19 + * 1.20 + * template<class SmartPtr> 1.21 + * void ClearOnShutdown(SmartPtr *aPtr) 1.22 + * 1.23 + * This function takes a pointer to a smart pointer and nulls the smart pointer 1.24 + * on shutdown. 1.25 + * 1.26 + * This is useful if you have a global smart pointer object which you don't 1.27 + * want to "leak" on shutdown. 1.28 + * 1.29 + * Although ClearOnShutdown will work with any smart pointer (i.e., nsCOMPtr, 1.30 + * nsRefPtr, nsAutoPtr, StaticRefPtr, and StaticAutoPtr), you probably want to 1.31 + * use it only with StaticRefPtr and StaticAutoPtr. There is no way to undo a 1.32 + * call to ClearOnShutdown, so you can call it only on smart pointers which you 1.33 + * know will live until the program shuts down. In practice, these are likely 1.34 + * global variables, which should be Static{Ref,Auto}Ptr. 1.35 + * 1.36 + * ClearOnShutdown is currently main-thread only because we don't want to 1.37 + * accidentally free an object from a different thread than the one it was 1.38 + * created on. 1.39 + */ 1.40 + 1.41 +namespace mozilla { 1.42 +namespace ClearOnShutdown_Internal { 1.43 + 1.44 +class ShutdownObserver : public LinkedListElement<ShutdownObserver> 1.45 +{ 1.46 +public: 1.47 + virtual void Shutdown() = 0; 1.48 + virtual ~ShutdownObserver() {} 1.49 +}; 1.50 + 1.51 +template<class SmartPtr> 1.52 +class PointerClearer : public ShutdownObserver 1.53 +{ 1.54 +public: 1.55 + PointerClearer(SmartPtr *aPtr) 1.56 + : mPtr(aPtr) 1.57 + {} 1.58 + 1.59 + virtual void Shutdown() 1.60 + { 1.61 + if (mPtr) { 1.62 + *mPtr = nullptr; 1.63 + } 1.64 + } 1.65 + 1.66 +private: 1.67 + SmartPtr *mPtr; 1.68 +}; 1.69 + 1.70 +extern bool sHasShutDown; 1.71 +extern StaticAutoPtr<LinkedList<ShutdownObserver> > sShutdownObservers; 1.72 + 1.73 +} // namespace ClearOnShutdown_Internal 1.74 + 1.75 +template<class SmartPtr> 1.76 +inline void ClearOnShutdown(SmartPtr *aPtr) 1.77 +{ 1.78 + using namespace ClearOnShutdown_Internal; 1.79 + 1.80 + MOZ_ASSERT(NS_IsMainThread()); 1.81 + MOZ_ASSERT(!sHasShutDown); 1.82 + 1.83 + if (!sShutdownObservers) { 1.84 + sShutdownObservers = new LinkedList<ShutdownObserver>(); 1.85 + } 1.86 + sShutdownObservers->insertBack(new PointerClearer<SmartPtr>(aPtr)); 1.87 +} 1.88 + 1.89 +// Called when XPCOM is shutting down, after all shutdown notifications have 1.90 +// been sent and after all threads' event loops have been purged. 1.91 +inline void KillClearOnShutdown() 1.92 +{ 1.93 + using namespace ClearOnShutdown_Internal; 1.94 + 1.95 + MOZ_ASSERT(NS_IsMainThread()); 1.96 + 1.97 + if (sShutdownObservers) { 1.98 + ShutdownObserver *observer; 1.99 + while ((observer = sShutdownObservers->popFirst())) { 1.100 + observer->Shutdown(); 1.101 + delete observer; 1.102 + } 1.103 + } 1.104 + 1.105 + sShutdownObservers = nullptr; 1.106 + sHasShutDown = true; 1.107 +} 1.108 + 1.109 +} // namespace mozilla 1.110 + 1.111 +#endif