]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/CleanUp.h
Merge from head
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Utility / CleanUp.h
1 //===-- CleanUp.h -----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_CleanUp_h_
11 #define liblldb_CleanUp_h_
12
13 #include "lldb/lldb-public.h"
14 #include <functional>
15
16 namespace lldb_utility {
17
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.
26 //
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 
32 // into T.
33 //
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.
38 //
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.
43 //
44 // EXAMPLES
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:
50 //
51 //  CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close);
52 //
53 //  // malloc/free example
54 //  CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free);
55 //----------------------------------------------------------------------
56 template <typename T, typename R = void>
57 class CleanUp
58 {
59 public:
60     typedef T value_type;
61     typedef std::function<R(value_type)> CallbackType;
62
63     //----------------------------------------------------------------------
64     // Constructor that sets the current value only. No values are 
65     // considered to be invalid and the cleanup function will be called
66     // regardless of the value of m_current_value.
67     //----------------------------------------------------------------------
68     CleanUp (value_type value, CallbackType callback) : 
69         m_current_value (value),
70         m_invalid_value (),
71         m_callback (callback),
72         m_callback_called (false),
73         m_invalid_value_is_valid (false)
74     {
75     }
76
77     //----------------------------------------------------------------------
78     // Constructor that sets the current value and also the invalid value.
79     // The cleanup function will be called on "m_value" as long as it isn't
80     // equal to "m_invalid_value".
81     //----------------------------------------------------------------------
82     CleanUp (value_type value, value_type invalid, CallbackType callback) : 
83         m_current_value (value),
84         m_invalid_value (invalid),
85         m_callback (callback),
86         m_callback_called (false),
87         m_invalid_value_is_valid (true)
88     {
89     }
90
91     //----------------------------------------------------------------------
92     // Automatically cleanup when this object goes out of scope.
93     //----------------------------------------------------------------------
94     ~CleanUp ()
95     {
96         clean();
97     }
98
99     //----------------------------------------------------------------------
100     // Access the value stored in this class
101     //----------------------------------------------------------------------
102     value_type get() 
103     {
104         return m_current_value; 
105     }
106
107     //----------------------------------------------------------------------
108     // Access the value stored in this class
109     //----------------------------------------------------------------------
110     const value_type
111     get() const 
112     {
113         return m_current_value; 
114     }
115
116     //----------------------------------------------------------------------
117     // Reset the owned value to "value". If a current value is valid and
118     // the cleanup callback hasn't been called, the previous value will
119     // be cleaned up (see void CleanUp::clean()). 
120     //----------------------------------------------------------------------
121     void 
122     set (const value_type value)
123     {
124         // Cleanup the current value if needed
125         clean ();
126         // Now set the new value and mark our callback as not called
127         m_callback_called = false;
128         m_current_value = value;
129     }
130
131     //----------------------------------------------------------------------
132     // Checks is "m_current_value" is valid. The value is considered valid
133     // no invalid value was supplied during construction of this object or
134     // if an invalid value was supplied and "m_current_value" is not equal
135     // to "m_invalid_value".
136     //
137     // Returns true if "m_current_value" is valid, false otherwise.
138     //----------------------------------------------------------------------
139     bool 
140     is_valid() const 
141     {
142         if (m_invalid_value_is_valid)
143             return m_current_value != m_invalid_value; 
144         return true;
145     }
146
147     //----------------------------------------------------------------------
148     // This function will call the cleanup callback provided in the 
149     // constructor one time if the value is considered valid (See is_valid()).
150     // This function sets m_callback_called to true so we don't call the
151     // cleanup callback multiple times on the same value.
152     //----------------------------------------------------------------------
153     void 
154     clean()
155     {
156         if (m_callback && !m_callback_called)
157         {
158             m_callback_called = true;
159             if (is_valid())
160                 m_callback(m_current_value);
161         }
162     }
163
164     //----------------------------------------------------------------------
165     // Cancels the cleanup that would have been called on "m_current_value" 
166     // if it was valid. This function can be used to release the value 
167     // contained in this object so ownership can be transferred to the caller.
168     //----------------------------------------------------------------------
169     value_type
170     release ()
171     {
172         m_callback_called = true;
173         return m_current_value;
174     }
175
176 private:
177             value_type      m_current_value;
178     const   value_type      m_invalid_value;
179             CallbackType    m_callback;
180             bool            m_callback_called;
181             bool            m_invalid_value_is_valid;
182
183     // Outlaw default constructor, copy constructor and the assignment operator
184     DISALLOW_COPY_AND_ASSIGN (CleanUp);                 
185 };
186     
187 template <typename T, typename R, typename A0>
188 class CleanUp2
189 {
190 public:
191     typedef T value_type;
192     typedef std::function<R(value_type,A0)> CallbackType;
193     
194     //----------------------------------------------------------------------
195     // Constructor that sets the current value only. No values are 
196     // considered to be invalid and the cleanup function will be called
197     // regardless of the value of m_current_value.
198     //----------------------------------------------------------------------
199     CleanUp2 (value_type value, CallbackType callback, A0 arg) : 
200     m_current_value (value),
201     m_invalid_value (),
202     m_callback (callback),
203     m_callback_called (false),
204     m_invalid_value_is_valid (false),
205     m_argument(arg)
206     {
207     }
208     
209     //----------------------------------------------------------------------
210     // Constructor that sets the current value and also the invalid value.
211     // The cleanup function will be called on "m_value" as long as it isn't
212     // equal to "m_invalid_value".
213     //----------------------------------------------------------------------
214     CleanUp2 (value_type value, value_type invalid, CallbackType callback, A0 arg) : 
215     m_current_value (value),
216     m_invalid_value (invalid),
217     m_callback (callback),
218     m_callback_called (false),
219     m_invalid_value_is_valid (true),
220     m_argument(arg)
221     {
222     }
223     
224     //----------------------------------------------------------------------
225     // Automatically cleanup when this object goes out of scope.
226     //----------------------------------------------------------------------
227     ~CleanUp2 ()
228     {
229         clean();
230     }
231     
232     //----------------------------------------------------------------------
233     // Access the value stored in this class
234     //----------------------------------------------------------------------
235     value_type get() 
236     {
237         return m_current_value; 
238     }
239     
240     //----------------------------------------------------------------------
241     // Access the value stored in this class
242     //----------------------------------------------------------------------
243     const value_type
244     get() const 
245     {
246         return m_current_value; 
247     }
248     
249     //----------------------------------------------------------------------
250     // Reset the owned value to "value". If a current value is valid and
251     // the cleanup callback hasn't been called, the previous value will
252     // be cleaned up (see void CleanUp::clean()). 
253     //----------------------------------------------------------------------
254     void 
255     set (const value_type value)
256     {
257         // Cleanup the current value if needed
258         clean ();
259         // Now set the new value and mark our callback as not called
260         m_callback_called = false;
261         m_current_value = value;
262     }
263     
264     //----------------------------------------------------------------------
265     // Checks is "m_current_value" is valid. The value is considered valid
266     // no invalid value was supplied during construction of this object or
267     // if an invalid value was supplied and "m_current_value" is not equal
268     // to "m_invalid_value".
269     //
270     // Returns true if "m_current_value" is valid, false otherwise.
271     //----------------------------------------------------------------------
272     bool 
273     is_valid() const 
274     {
275         if (m_invalid_value_is_valid)
276             return m_current_value != m_invalid_value; 
277         return true;
278     }
279     
280     //----------------------------------------------------------------------
281     // This function will call the cleanup callback provided in the 
282     // constructor one time if the value is considered valid (See is_valid()).
283     // This function sets m_callback_called to true so we don't call the
284     // cleanup callback multiple times on the same value.
285     //----------------------------------------------------------------------
286     void 
287     clean()
288     {
289         if (m_callback && !m_callback_called)
290         {
291             m_callback_called = true;
292             if (is_valid())
293                 m_callback(m_current_value, m_argument);
294         }
295     }
296     
297     //----------------------------------------------------------------------
298     // Cancels the cleanup that would have been called on "m_current_value" 
299     // if it was valid. This function can be used to release the value 
300     // contained in this object so ownership can be transferred to the caller.
301     //----------------------------------------------------------------------
302     value_type
303     release ()
304     {
305         m_callback_called = true;
306         return m_current_value;
307     }
308     
309 private:
310     value_type      m_current_value;
311     const   value_type      m_invalid_value;
312     CallbackType    m_callback;
313     bool            m_callback_called;
314     bool            m_invalid_value_is_valid;
315     A0              m_argument;
316     
317     // Outlaw default constructor, copy constructor and the assignment operator
318     DISALLOW_COPY_AND_ASSIGN (CleanUp2);                 
319 };
320
321 } // namespace lldb_utility
322
323 #endif // #ifndef liblldb_CleanUp_h_