1 //===-- CleanUp.h -----------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_CleanUp_h_
11 #define liblldb_CleanUp_h_
13 #include "lldb/lldb-public.h"
16 namespace lldb_utility {
18 //----------------------------------------------------------------------
19 // Templated class that guarantees that a cleanup callback function will
20 // be called. The cleanup function will be called once under the
21 // following conditions:
22 // - when the object goes out of scope
23 // - when the user explicitly calls clean.
24 // - the current value will be cleaned up when a new value is set using
25 // set(T value) as long as the current value hasn't already been cleaned.
27 // This class is designed to be used with simple types for type T (like
28 // file descriptors, opaque handles, pointers, etc). If more complex
29 // type T objects are desired, we need to probably specialize this class
30 // to take "const T&" for all input T parameters. Yet if a type T is
31 // complex already it might be better to build the cleanup functionality
34 // The cleanup function must take one argument that is of type T.
35 // The calback function return type is R. The return value is currently
36 // needed for "CallbackType". If there is an easy way to get around the
37 // need for the return value we can change this class.
39 // The two template parameters are:
40 // T - The variable type of value that will be stored and used as the
41 // sole argument for the cleanup callback.
42 // R - The return type for the cleanup function.
45 // // Use with file handles that get opened where you want to close
46 // // them. Below we use "int open(const char *path, int oflag, ...)"
47 // // which returns an integer file descriptor. -1 is the invalid file
48 // // descriptor so to make an object that will call "int close(int fd)"
49 // // automatically we can use:
51 // CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close);
53 // // malloc/free example
54 // CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free);
55 //----------------------------------------------------------------------
56 template <typename T, typename R = void> class CleanUp {
59 typedef std::function<R(value_type)> CallbackType;
61 //----------------------------------------------------------------------
62 // Constructor that sets the current value only. No values are
63 // considered to be invalid and the cleanup function will be called
64 // regardless of the value of m_current_value.
65 //----------------------------------------------------------------------
66 CleanUp(value_type value, CallbackType callback)
67 : m_current_value(value), m_invalid_value(), m_callback(callback),
68 m_callback_called(false), m_invalid_value_is_valid(false) {}
70 //----------------------------------------------------------------------
71 // Constructor that sets the current value and also the invalid value.
72 // The cleanup function will be called on "m_value" as long as it isn't
73 // equal to "m_invalid_value".
74 //----------------------------------------------------------------------
75 CleanUp(value_type value, value_type invalid, CallbackType callback)
76 : m_current_value(value), m_invalid_value(invalid), m_callback(callback),
77 m_callback_called(false), m_invalid_value_is_valid(true) {}
79 //----------------------------------------------------------------------
80 // Automatically cleanup when this object goes out of scope.
81 //----------------------------------------------------------------------
82 ~CleanUp() { clean(); }
84 //----------------------------------------------------------------------
85 // Access the value stored in this class
86 //----------------------------------------------------------------------
87 value_type get() { return m_current_value; }
89 //----------------------------------------------------------------------
90 // Access the value stored in this class
91 //----------------------------------------------------------------------
92 const value_type get() const { return m_current_value; }
94 //----------------------------------------------------------------------
95 // Reset the owned value to "value". If a current value is valid and
96 // the cleanup callback hasn't been called, the previous value will
97 // be cleaned up (see void CleanUp::clean()).
98 //----------------------------------------------------------------------
99 void set(const value_type value) {
100 // Cleanup the current value if needed
102 // Now set the new value and mark our callback as not called
103 m_callback_called = false;
104 m_current_value = value;
107 //----------------------------------------------------------------------
108 // Checks is "m_current_value" is valid. The value is considered valid
109 // no invalid value was supplied during construction of this object or
110 // if an invalid value was supplied and "m_current_value" is not equal
111 // to "m_invalid_value".
113 // Returns true if "m_current_value" is valid, false otherwise.
114 //----------------------------------------------------------------------
115 bool is_valid() const {
116 if (m_invalid_value_is_valid)
117 return m_current_value != m_invalid_value;
121 //----------------------------------------------------------------------
122 // This function will call the cleanup callback provided in the
123 // constructor one time if the value is considered valid (See is_valid()).
124 // This function sets m_callback_called to true so we don't call the
125 // cleanup callback multiple times on the same value.
126 //----------------------------------------------------------------------
128 if (m_callback && !m_callback_called) {
129 m_callback_called = true;
131 m_callback(m_current_value);
135 //----------------------------------------------------------------------
136 // Cancels the cleanup that would have been called on "m_current_value"
137 // if it was valid. This function can be used to release the value
138 // contained in this object so ownership can be transferred to the caller.
139 //----------------------------------------------------------------------
140 value_type release() {
141 m_callback_called = true;
142 return m_current_value;
146 value_type m_current_value;
147 const value_type m_invalid_value;
148 CallbackType m_callback;
149 bool m_callback_called;
150 bool m_invalid_value_is_valid;
152 // Outlaw default constructor, copy constructor and the assignment operator
153 DISALLOW_COPY_AND_ASSIGN(CleanUp);
156 template <typename T, typename R, typename A0> class CleanUp2 {
158 typedef T value_type;
159 typedef std::function<R(value_type, A0)> CallbackType;
161 //----------------------------------------------------------------------
162 // Constructor that sets the current value only. No values are
163 // considered to be invalid and the cleanup function will be called
164 // regardless of the value of m_current_value.
165 //----------------------------------------------------------------------
166 CleanUp2(value_type value, CallbackType callback, A0 arg)
167 : m_current_value(value), m_invalid_value(), m_callback(callback),
168 m_callback_called(false), m_invalid_value_is_valid(false),
171 //----------------------------------------------------------------------
172 // Constructor that sets the current value and also the invalid value.
173 // The cleanup function will be called on "m_value" as long as it isn't
174 // equal to "m_invalid_value".
175 //----------------------------------------------------------------------
176 CleanUp2(value_type value, value_type invalid, CallbackType callback, A0 arg)
177 : m_current_value(value), m_invalid_value(invalid), m_callback(callback),
178 m_callback_called(false), m_invalid_value_is_valid(true),
181 //----------------------------------------------------------------------
182 // Automatically cleanup when this object goes out of scope.
183 //----------------------------------------------------------------------
184 ~CleanUp2() { clean(); }
186 //----------------------------------------------------------------------
187 // Access the value stored in this class
188 //----------------------------------------------------------------------
189 value_type get() { return m_current_value; }
191 //----------------------------------------------------------------------
192 // Access the value stored in this class
193 //----------------------------------------------------------------------
194 const value_type get() const { return m_current_value; }
196 //----------------------------------------------------------------------
197 // Reset the owned value to "value". If a current value is valid and
198 // the cleanup callback hasn't been called, the previous value will
199 // be cleaned up (see void CleanUp::clean()).
200 //----------------------------------------------------------------------
201 void set(const value_type value) {
202 // Cleanup the current value if needed
204 // Now set the new value and mark our callback as not called
205 m_callback_called = false;
206 m_current_value = value;
209 //----------------------------------------------------------------------
210 // Checks is "m_current_value" is valid. The value is considered valid
211 // no invalid value was supplied during construction of this object or
212 // if an invalid value was supplied and "m_current_value" is not equal
213 // to "m_invalid_value".
215 // Returns true if "m_current_value" is valid, false otherwise.
216 //----------------------------------------------------------------------
217 bool is_valid() const {
218 if (m_invalid_value_is_valid)
219 return m_current_value != m_invalid_value;
223 //----------------------------------------------------------------------
224 // This function will call the cleanup callback provided in the
225 // constructor one time if the value is considered valid (See is_valid()).
226 // This function sets m_callback_called to true so we don't call the
227 // cleanup callback multiple times on the same value.
228 //----------------------------------------------------------------------
230 if (m_callback && !m_callback_called) {
231 m_callback_called = true;
233 m_callback(m_current_value, m_argument);
237 //----------------------------------------------------------------------
238 // Cancels the cleanup that would have been called on "m_current_value"
239 // if it was valid. This function can be used to release the value
240 // contained in this object so ownership can be transferred to the caller.
241 //----------------------------------------------------------------------
242 value_type release() {
243 m_callback_called = true;
244 return m_current_value;
248 value_type m_current_value;
249 const value_type m_invalid_value;
250 CallbackType m_callback;
251 bool m_callback_called;
252 bool m_invalid_value_is_valid;
255 // Outlaw default constructor, copy constructor and the assignment operator
256 DISALLOW_COPY_AND_ASSIGN(CleanUp2);
259 } // namespace lldb_utility
261 #endif // #ifndef liblldb_CleanUp_h_