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
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.
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"
58 * Scoped is a helper to create RAII wrappers
59 * Type argument |Traits| is expected to have the following structure:
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);
71 template<typename Traits
>
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
)
86 MOZ_GUARD_OBJECT_NOTIFIER_INIT
;
89 Traits::release(value
);
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
106 * @return The original resource.
109 Resource tmp
= value
;
110 value
= Traits::empty();
115 * Perform immediate clean-up of this |Scoped|.
117 * If this |Scoped| is currently empty, this method has no effect.
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|.
136 Scoped
<Traits
>& operator=(const Resource
& other
) {
139 Scoped
<Traits
>& reset(const Resource
& other
) {
140 Traits::release(value
);
146 explicit Scoped(const Scoped
<Traits
>& value
) MOZ_DELETE
;
147 Scoped
<Traits
>& operator=(const Scoped
<Traits
>& value
) MOZ_DELETE
;
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
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); \
172 explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
173 : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
175 explicit name(Resource ptr \
176 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
177 : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
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.
188 * ScopedFreePtr<S> foo = malloc(sizeof(S));
189 * ScopedFreePtr<char> bar = strdup(str);
192 struct ScopedFreePtrTraits
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.
204 * ScopedDeletePtr<S> foo = new S();
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.
217 * ScopedDeleteArray<S> foo = new S[42];
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_