summaryrefslogtreecommitdiff
path: root/include/lldb/Utility/CleanUp.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Utility/CleanUp.h')
-rw-r--r--include/lldb/Utility/CleanUp.h322
1 files changed, 322 insertions, 0 deletions
diff --git a/include/lldb/Utility/CleanUp.h b/include/lldb/Utility/CleanUp.h
new file mode 100644
index 0000000000000..ab15d1999b7d4
--- /dev/null
+++ b/include/lldb/Utility/CleanUp.h
@@ -0,0 +1,322 @@
+//===-- CleanUp.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CleanUp_h_
+#define liblldb_CleanUp_h_
+
+#include "lldb/lldb-public.h"
+
+namespace lldb_utility {
+
+//----------------------------------------------------------------------
+// Templated class that guarantees that a cleanup callback function will
+// be called. The cleanup function will be called once under the
+// following conditions:
+// - when the object goes out of scope
+// - when the user explicitly calls clean.
+// - the current value will be cleaned up when a new value is set using
+// set(T value) as long as the current value hasn't already been cleaned.
+//
+// This class is designed to be used with simple types for type T (like
+// file descriptors, opaque handles, pointers, etc). If more complex
+// type T objects are desired, we need to probably specialize this class
+// to take "const T&" for all input T parameters. Yet if a type T is
+// complex already it might be better to build the cleanup funcionality
+// into T.
+//
+// The cleanup function must take one argument that is of type T.
+// The calback function return type is R. The return value is currently
+// needed for "CallbackType". If there is an easy way to get around the
+// need for the return value we can change this class.
+//
+// The two template parameters are:
+// T - The variable type of value that will be stored and used as the
+// sole argument for the cleanup callback.
+// R - The return type for the cleanup function.
+//
+// EXAMPLES
+// // Use with file handles that get opened where you want to close
+// // them. Below we use "int open(const char *path, int oflag, ...)"
+// // which returns an integer file descriptor. -1 is the invalid file
+// // descriptor so to make an object that will call "int close(int fd)"
+// // automatically we can use:
+//
+// CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close);
+//
+// // malloc/free example
+// CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free);
+//----------------------------------------------------------------------
+template <typename T, typename R = void>
+class CleanUp
+{
+public:
+ typedef T value_type;
+ typedef R (*CallbackType)(value_type);
+
+ //----------------------------------------------------------------------
+ // Constructor that sets the current value only. No values are
+ // considered to be invalid and the cleanup function will be called
+ // regardless of the value of m_current_value.
+ //----------------------------------------------------------------------
+ CleanUp (value_type value, CallbackType callback) :
+ m_current_value (value),
+ m_invalid_value (),
+ m_callback (callback),
+ m_callback_called (false),
+ m_invalid_value_is_valid (false)
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Constructor that sets the current value and also the invalid value.
+ // The cleanup function will be called on "m_value" as long as it isn't
+ // equal to "m_invalid_value".
+ //----------------------------------------------------------------------
+ CleanUp (value_type value, value_type invalid, CallbackType callback) :
+ m_current_value (value),
+ m_invalid_value (invalid),
+ m_callback (callback),
+ m_callback_called (false),
+ m_invalid_value_is_valid (true)
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Automatically cleanup when this object goes out of scope.
+ //----------------------------------------------------------------------
+ ~CleanUp ()
+ {
+ clean();
+ }
+
+ //----------------------------------------------------------------------
+ // Access the value stored in this class
+ //----------------------------------------------------------------------
+ value_type get()
+ {
+ return m_current_value;
+ }
+
+ //----------------------------------------------------------------------
+ // Access the value stored in this class
+ //----------------------------------------------------------------------
+ const value_type
+ get() const
+ {
+ return m_current_value;
+ }
+
+ //----------------------------------------------------------------------
+ // Reset the owned value to "value". If a current value is valid and
+ // the cleanup callback hasn't been called, the previous value will
+ // be cleaned up (see void CleanUp::clean()).
+ //----------------------------------------------------------------------
+ void
+ set (const value_type value)
+ {
+ // Cleanup the current value if needed
+ clean ();
+ // Now set the new value and mark our callback as not called
+ m_callback_called = false;
+ m_current_value = value;
+ }
+
+ //----------------------------------------------------------------------
+ // Checks is "m_current_value" is valid. The value is considered valid
+ // no invalid value was supplied during construction of this object or
+ // if an invalid value was supplied and "m_current_value" is not equal
+ // to "m_invalid_value".
+ //
+ // Returns true if "m_current_value" is valid, false otherwise.
+ //----------------------------------------------------------------------
+ bool
+ is_valid() const
+ {
+ if (m_invalid_value_is_valid)
+ return m_current_value != m_invalid_value;
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ // This function will call the cleanup callback provided in the
+ // constructor one time if the value is considered valid (See is_valid()).
+ // This function sets m_callback_called to true so we don't call the
+ // cleanup callback multiple times on the same value.
+ //----------------------------------------------------------------------
+ void
+ clean()
+ {
+ if (m_callback && !m_callback_called)
+ {
+ m_callback_called = true;
+ if (is_valid())
+ m_callback(m_current_value);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Cancels the cleanup that would have been called on "m_current_value"
+ // if it was valid. This function can be used to release the value
+ // contained in this object so ownership can be transfered to the caller.
+ //----------------------------------------------------------------------
+ value_type
+ release ()
+ {
+ m_callback_called = true;
+ return m_current_value;
+ }
+
+private:
+ value_type m_current_value;
+ const value_type m_invalid_value;
+ CallbackType m_callback;
+ bool m_callback_called;
+ bool m_invalid_value_is_valid;
+
+ // Outlaw default constructor, copy constructor and the assignment operator
+ DISALLOW_COPY_AND_ASSIGN (CleanUp);
+};
+
+template <typename T, typename R, typename A0>
+class CleanUp2
+{
+public:
+ typedef T value_type;
+ typedef R (*CallbackType)(value_type, A0);
+
+ //----------------------------------------------------------------------
+ // Constructor that sets the current value only. No values are
+ // considered to be invalid and the cleanup function will be called
+ // regardless of the value of m_current_value.
+ //----------------------------------------------------------------------
+ CleanUp2 (value_type value, CallbackType callback, A0 arg) :
+ m_current_value (value),
+ m_invalid_value (),
+ m_callback (callback),
+ m_callback_called (false),
+ m_invalid_value_is_valid (false),
+ m_argument(arg)
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Constructor that sets the current value and also the invalid value.
+ // The cleanup function will be called on "m_value" as long as it isn't
+ // equal to "m_invalid_value".
+ //----------------------------------------------------------------------
+ CleanUp2 (value_type value, value_type invalid, CallbackType callback, A0 arg) :
+ m_current_value (value),
+ m_invalid_value (invalid),
+ m_callback (callback),
+ m_callback_called (false),
+ m_invalid_value_is_valid (true),
+ m_argument(arg)
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Automatically cleanup when this object goes out of scope.
+ //----------------------------------------------------------------------
+ ~CleanUp2 ()
+ {
+ clean();
+ }
+
+ //----------------------------------------------------------------------
+ // Access the value stored in this class
+ //----------------------------------------------------------------------
+ value_type get()
+ {
+ return m_current_value;
+ }
+
+ //----------------------------------------------------------------------
+ // Access the value stored in this class
+ //----------------------------------------------------------------------
+ const value_type
+ get() const
+ {
+ return m_current_value;
+ }
+
+ //----------------------------------------------------------------------
+ // Reset the owned value to "value". If a current value is valid and
+ // the cleanup callback hasn't been called, the previous value will
+ // be cleaned up (see void CleanUp::clean()).
+ //----------------------------------------------------------------------
+ void
+ set (const value_type value)
+ {
+ // Cleanup the current value if needed
+ clean ();
+ // Now set the new value and mark our callback as not called
+ m_callback_called = false;
+ m_current_value = value;
+ }
+
+ //----------------------------------------------------------------------
+ // Checks is "m_current_value" is valid. The value is considered valid
+ // no invalid value was supplied during construction of this object or
+ // if an invalid value was supplied and "m_current_value" is not equal
+ // to "m_invalid_value".
+ //
+ // Returns true if "m_current_value" is valid, false otherwise.
+ //----------------------------------------------------------------------
+ bool
+ is_valid() const
+ {
+ if (m_invalid_value_is_valid)
+ return m_current_value != m_invalid_value;
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ // This function will call the cleanup callback provided in the
+ // constructor one time if the value is considered valid (See is_valid()).
+ // This function sets m_callback_called to true so we don't call the
+ // cleanup callback multiple times on the same value.
+ //----------------------------------------------------------------------
+ void
+ clean()
+ {
+ if (m_callback && !m_callback_called)
+ {
+ m_callback_called = true;
+ if (is_valid())
+ m_callback(m_current_value, m_argument);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Cancels the cleanup that would have been called on "m_current_value"
+ // if it was valid. This function can be used to release the value
+ // contained in this object so ownership can be transfered to the caller.
+ //----------------------------------------------------------------------
+ value_type
+ release ()
+ {
+ m_callback_called = true;
+ return m_current_value;
+ }
+
+private:
+ value_type m_current_value;
+ const value_type m_invalid_value;
+ CallbackType m_callback;
+ bool m_callback_called;
+ bool m_invalid_value_is_valid;
+ A0 m_argument;
+
+ // Outlaw default constructor, copy constructor and the assignment operator
+ DISALLOW_COPY_AND_ASSIGN (CleanUp2);
+};
+
+} // namespace lldb_utility
+
+#endif // #ifndef liblldb_CleanUp_h_