Bug 785860 - fix sts preload list tests to skip private mode tests if private browsin...
[gecko.git] / mfbt / Scoped.h
blobb811a47d5e443466fe43cbbaa9e47ba57aca76a9
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* A number of structures to simplify scope-based RAII management. */
7 #ifndef mozilla_Scoped_h_
8 #define mozilla_Scoped_h_
11 * Resource Acquisition Is Initialization is a programming idiom used
12 * to write robust code that is able to deallocate resources properly,
13 * even in presence of execution errors or exceptions that need to be
14 * propagated. The Scoped* classes defined in this header perform the
15 * deallocation of the resource they hold once program execution
16 * reaches the end of the scope for which they have been defined.
18 * This header provides the following RAII classes:
20 * - |ScopedFreePtr| - a container for a pointer, that automatically calls
21 * |free()| at the end of the scope;
22 * - |ScopedDeletePtr| - a container for a pointer, that automatically calls
23 * |delete| at the end of the scope;
24 * - |ScopedDeleteArray| - a container for a pointer to an array, that
25 * automatically calls |delete[]| at the end of the scope.
27 * The general scenario for each of the RAII classes is the following:
29 * ScopedClass foo(create_value());
30 * // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
31 * to access the value.
32 * // ... In case of |return| or |throw|, |foo| is deallocated automatically.
33 * // ... If |foo| needs to be returned or stored, use |foo.forget()|
35 * Note that the RAII classes defined in this header do _not_ perform any form
36 * of reference-counting or garbage-collection. These classes have exactly two
37 * behaviors:
39 * - if |forget()| has not been called, the resource is always deallocated at
40 * the end of the scope;
41 * - if |forget()| has been called, any control on the resource is unbound
42 * and the resource is not deallocated by the class.
44 * Extension:
46 * In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
47 * to simplify the definition of RAII classes for other scenarios. These macros
48 * have been used to automatically close file descriptors/file handles when
49 * reaching the end of the scope, graphics contexts, etc.
52 #include "mozilla/Attributes.h"
53 #include "mozilla/GuardObjects.h"
55 namespace mozilla {
58 * Scoped is a helper to create RAII wrappers
59 * Type argument |Traits| is expected to have the following structure:
61 * struct Traits {
62 * // Define the type of the value stored in the wrapper
63 * typedef value_type type;
64 * // Returns the value corresponding to the uninitialized or freed state
65 * const static type empty();
66 * // Release resources corresponding to the wrapped value
67 * // This function is responsible for not releasing an |empty| value
68 * const static void release(type);
69 * }
71 template<typename Traits>
72 class Scoped
74 public:
75 typedef typename Traits::type Resource;
77 explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
78 : value(Traits::empty())
80 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
82 explicit Scoped(const Resource& value
83 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
84 : value(value)
86 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
88 ~Scoped() {
89 Traits::release(value);
92 // Constant getter
93 operator const Resource&() const { return value; }
94 const Resource& operator->() const { return value; }
95 const Resource& get() const { return value; }
96 // Non-constant getter.
97 Resource& rwget() { return value; }
100 * Forget the resource.
102 * Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
103 * have no effect at destruction (unless it is reset to another resource by
104 * |operator=|).
106 * @return The original resource.
108 Resource forget() {
109 Resource tmp = value;
110 value = Traits::empty();
111 return tmp;
115 * Perform immediate clean-up of this |Scoped|.
117 * If this |Scoped| is currently empty, this method has no effect.
119 void dispose() {
120 Traits::release(value);
121 value = Traits::empty();
124 bool operator==(const Resource& other) const {
125 return value == other;
129 * Replace the resource with another resource.
131 * Calling |operator=| has the side-effect of triggering clean-up. If you do
132 * not want to trigger clean-up, you should first invoke |forget|.
134 * @return this
136 Scoped<Traits>& operator=(const Resource& other) {
137 return reset(other);
139 Scoped<Traits>& reset(const Resource& other) {
140 Traits::release(value);
141 value = other;
142 return *this;
145 private:
146 explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
147 Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
149 private:
150 Resource value;
151 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
155 * SCOPED_TEMPLATE defines a templated class derived from Scoped
156 * This allows to implement templates such as ScopedFreePtr.
158 * @param name The name of the class to define.
159 * @param Traits A struct implementing clean-up. See the implementations
160 * for more details.
162 #define SCOPED_TEMPLATE(name, Traits) \
163 template<typename Type> \
164 struct name : public mozilla::Scoped<Traits<Type> > \
166 typedef mozilla::Scoped<Traits<Type> > Super; \
167 typedef typename Super::Resource Resource; \
168 name& operator=(Resource ptr) { \
169 Super::operator=(ptr); \
170 return *this; \
172 explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
173 : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
174 {} \
175 explicit name(Resource ptr \
176 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
177 : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
178 {} \
179 private: \
180 explicit name(name& source) MOZ_DELETE; \
181 name& operator=(name& source) MOZ_DELETE; \
185 * ScopedFreePtr is a RAII wrapper for pointers that need to be free()d.
187 * struct S { ... };
188 * ScopedFreePtr<S> foo = malloc(sizeof(S));
189 * ScopedFreePtr<char> bar = strdup(str);
191 template<typename T>
192 struct ScopedFreePtrTraits
194 typedef T* type;
195 static T* empty() { return NULL; }
196 static void release(T* ptr) { free(ptr); }
198 SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
201 * ScopedDeletePtr is a RAII wrapper for pointers that need to be deleted.
203 * struct S { ... };
204 * ScopedDeletePtr<S> foo = new S();
206 template<typename T>
207 struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
209 static void release(T* ptr) { delete ptr; }
211 SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
214 * ScopedDeleteArray is a RAII wrapper for pointers that need to be delete[]ed.
216 * struct S { ... };
217 * ScopedDeleteArray<S> foo = new S[42];
219 template<typename T>
220 struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
222 static void release(T* ptr) { delete [] ptr; }
224 SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
226 } /* namespace mozilla */
228 #endif // mozilla_Scoped_h_