1254721Semaste//===-- CleanUp.h -----------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#ifndef liblldb_CleanUp_h_ 11254721Semaste#define liblldb_CleanUp_h_ 12254721Semaste 13254721Semaste#include "lldb/lldb-public.h" 14254721Semaste 15254721Semastenamespace lldb_utility { 16254721Semaste 17254721Semaste//---------------------------------------------------------------------- 18254721Semaste// Templated class that guarantees that a cleanup callback function will 19254721Semaste// be called. The cleanup function will be called once under the 20254721Semaste// following conditions: 21254721Semaste// - when the object goes out of scope 22254721Semaste// - when the user explicitly calls clean. 23254721Semaste// - the current value will be cleaned up when a new value is set using 24254721Semaste// set(T value) as long as the current value hasn't already been cleaned. 25254721Semaste// 26254721Semaste// This class is designed to be used with simple types for type T (like 27254721Semaste// file descriptors, opaque handles, pointers, etc). If more complex 28254721Semaste// type T objects are desired, we need to probably specialize this class 29254721Semaste// to take "const T&" for all input T parameters. Yet if a type T is 30254721Semaste// complex already it might be better to build the cleanup funcionality 31254721Semaste// into T. 32254721Semaste// 33254721Semaste// The cleanup function must take one argument that is of type T. 34254721Semaste// The calback function return type is R. The return value is currently 35254721Semaste// needed for "CallbackType". If there is an easy way to get around the 36254721Semaste// need for the return value we can change this class. 37254721Semaste// 38254721Semaste// The two template parameters are: 39254721Semaste// T - The variable type of value that will be stored and used as the 40254721Semaste// sole argument for the cleanup callback. 41254721Semaste// R - The return type for the cleanup function. 42254721Semaste// 43254721Semaste// EXAMPLES 44254721Semaste// // Use with file handles that get opened where you want to close 45254721Semaste// // them. Below we use "int open(const char *path, int oflag, ...)" 46254721Semaste// // which returns an integer file descriptor. -1 is the invalid file 47254721Semaste// // descriptor so to make an object that will call "int close(int fd)" 48254721Semaste// // automatically we can use: 49254721Semaste// 50254721Semaste// CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close); 51254721Semaste// 52254721Semaste// // malloc/free example 53254721Semaste// CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free); 54254721Semaste//---------------------------------------------------------------------- 55254721Semastetemplate <typename T, typename R = void> 56254721Semasteclass CleanUp 57254721Semaste{ 58254721Semastepublic: 59254721Semaste typedef T value_type; 60254721Semaste typedef R (*CallbackType)(value_type); 61254721Semaste 62254721Semaste //---------------------------------------------------------------------- 63254721Semaste // Constructor that sets the current value only. No values are 64254721Semaste // considered to be invalid and the cleanup function will be called 65254721Semaste // regardless of the value of m_current_value. 66254721Semaste //---------------------------------------------------------------------- 67254721Semaste CleanUp (value_type value, CallbackType callback) : 68254721Semaste m_current_value (value), 69254721Semaste m_invalid_value (), 70254721Semaste m_callback (callback), 71254721Semaste m_callback_called (false), 72254721Semaste m_invalid_value_is_valid (false) 73254721Semaste { 74254721Semaste } 75254721Semaste 76254721Semaste //---------------------------------------------------------------------- 77254721Semaste // Constructor that sets the current value and also the invalid value. 78254721Semaste // The cleanup function will be called on "m_value" as long as it isn't 79254721Semaste // equal to "m_invalid_value". 80254721Semaste //---------------------------------------------------------------------- 81254721Semaste CleanUp (value_type value, value_type invalid, CallbackType callback) : 82254721Semaste m_current_value (value), 83254721Semaste m_invalid_value (invalid), 84254721Semaste m_callback (callback), 85254721Semaste m_callback_called (false), 86254721Semaste m_invalid_value_is_valid (true) 87254721Semaste { 88254721Semaste } 89254721Semaste 90254721Semaste //---------------------------------------------------------------------- 91254721Semaste // Automatically cleanup when this object goes out of scope. 92254721Semaste //---------------------------------------------------------------------- 93254721Semaste ~CleanUp () 94254721Semaste { 95254721Semaste clean(); 96254721Semaste } 97254721Semaste 98254721Semaste //---------------------------------------------------------------------- 99254721Semaste // Access the value stored in this class 100254721Semaste //---------------------------------------------------------------------- 101254721Semaste value_type get() 102254721Semaste { 103254721Semaste return m_current_value; 104254721Semaste } 105254721Semaste 106254721Semaste //---------------------------------------------------------------------- 107254721Semaste // Access the value stored in this class 108254721Semaste //---------------------------------------------------------------------- 109254721Semaste const value_type 110254721Semaste get() const 111254721Semaste { 112254721Semaste return m_current_value; 113254721Semaste } 114254721Semaste 115254721Semaste //---------------------------------------------------------------------- 116254721Semaste // Reset the owned value to "value". If a current value is valid and 117254721Semaste // the cleanup callback hasn't been called, the previous value will 118254721Semaste // be cleaned up (see void CleanUp::clean()). 119254721Semaste //---------------------------------------------------------------------- 120254721Semaste void 121254721Semaste set (const value_type value) 122254721Semaste { 123254721Semaste // Cleanup the current value if needed 124254721Semaste clean (); 125254721Semaste // Now set the new value and mark our callback as not called 126254721Semaste m_callback_called = false; 127254721Semaste m_current_value = value; 128254721Semaste } 129254721Semaste 130254721Semaste //---------------------------------------------------------------------- 131254721Semaste // Checks is "m_current_value" is valid. The value is considered valid 132254721Semaste // no invalid value was supplied during construction of this object or 133254721Semaste // if an invalid value was supplied and "m_current_value" is not equal 134254721Semaste // to "m_invalid_value". 135254721Semaste // 136254721Semaste // Returns true if "m_current_value" is valid, false otherwise. 137254721Semaste //---------------------------------------------------------------------- 138254721Semaste bool 139254721Semaste is_valid() const 140254721Semaste { 141254721Semaste if (m_invalid_value_is_valid) 142254721Semaste return m_current_value != m_invalid_value; 143254721Semaste return true; 144254721Semaste } 145254721Semaste 146254721Semaste //---------------------------------------------------------------------- 147254721Semaste // This function will call the cleanup callback provided in the 148254721Semaste // constructor one time if the value is considered valid (See is_valid()). 149254721Semaste // This function sets m_callback_called to true so we don't call the 150254721Semaste // cleanup callback multiple times on the same value. 151254721Semaste //---------------------------------------------------------------------- 152254721Semaste void 153254721Semaste clean() 154254721Semaste { 155254721Semaste if (m_callback && !m_callback_called) 156254721Semaste { 157254721Semaste m_callback_called = true; 158254721Semaste if (is_valid()) 159254721Semaste m_callback(m_current_value); 160254721Semaste } 161254721Semaste } 162254721Semaste 163254721Semaste //---------------------------------------------------------------------- 164254721Semaste // Cancels the cleanup that would have been called on "m_current_value" 165254721Semaste // if it was valid. This function can be used to release the value 166254721Semaste // contained in this object so ownership can be transfered to the caller. 167254721Semaste //---------------------------------------------------------------------- 168254721Semaste value_type 169254721Semaste release () 170254721Semaste { 171254721Semaste m_callback_called = true; 172254721Semaste return m_current_value; 173254721Semaste } 174254721Semaste 175254721Semasteprivate: 176254721Semaste value_type m_current_value; 177254721Semaste const value_type m_invalid_value; 178254721Semaste CallbackType m_callback; 179254721Semaste bool m_callback_called; 180254721Semaste bool m_invalid_value_is_valid; 181254721Semaste 182254721Semaste // Outlaw default constructor, copy constructor and the assignment operator 183254721Semaste DISALLOW_COPY_AND_ASSIGN (CleanUp); 184254721Semaste}; 185254721Semaste 186254721Semastetemplate <typename T, typename R, typename A0> 187254721Semasteclass CleanUp2 188254721Semaste{ 189254721Semastepublic: 190254721Semaste typedef T value_type; 191254721Semaste typedef R (*CallbackType)(value_type, A0); 192254721Semaste 193254721Semaste //---------------------------------------------------------------------- 194254721Semaste // Constructor that sets the current value only. No values are 195254721Semaste // considered to be invalid and the cleanup function will be called 196254721Semaste // regardless of the value of m_current_value. 197254721Semaste //---------------------------------------------------------------------- 198254721Semaste CleanUp2 (value_type value, CallbackType callback, A0 arg) : 199254721Semaste m_current_value (value), 200254721Semaste m_invalid_value (), 201254721Semaste m_callback (callback), 202254721Semaste m_callback_called (false), 203254721Semaste m_invalid_value_is_valid (false), 204254721Semaste m_argument(arg) 205254721Semaste { 206254721Semaste } 207254721Semaste 208254721Semaste //---------------------------------------------------------------------- 209254721Semaste // Constructor that sets the current value and also the invalid value. 210254721Semaste // The cleanup function will be called on "m_value" as long as it isn't 211254721Semaste // equal to "m_invalid_value". 212254721Semaste //---------------------------------------------------------------------- 213254721Semaste CleanUp2 (value_type value, value_type invalid, CallbackType callback, A0 arg) : 214254721Semaste m_current_value (value), 215254721Semaste m_invalid_value (invalid), 216254721Semaste m_callback (callback), 217254721Semaste m_callback_called (false), 218254721Semaste m_invalid_value_is_valid (true), 219254721Semaste m_argument(arg) 220254721Semaste { 221254721Semaste } 222254721Semaste 223254721Semaste //---------------------------------------------------------------------- 224254721Semaste // Automatically cleanup when this object goes out of scope. 225254721Semaste //---------------------------------------------------------------------- 226254721Semaste ~CleanUp2 () 227254721Semaste { 228254721Semaste clean(); 229254721Semaste } 230254721Semaste 231254721Semaste //---------------------------------------------------------------------- 232254721Semaste // Access the value stored in this class 233254721Semaste //---------------------------------------------------------------------- 234254721Semaste value_type get() 235254721Semaste { 236254721Semaste return m_current_value; 237254721Semaste } 238254721Semaste 239254721Semaste //---------------------------------------------------------------------- 240254721Semaste // Access the value stored in this class 241254721Semaste //---------------------------------------------------------------------- 242254721Semaste const value_type 243254721Semaste get() const 244254721Semaste { 245254721Semaste return m_current_value; 246254721Semaste } 247254721Semaste 248254721Semaste //---------------------------------------------------------------------- 249254721Semaste // Reset the owned value to "value". If a current value is valid and 250254721Semaste // the cleanup callback hasn't been called, the previous value will 251254721Semaste // be cleaned up (see void CleanUp::clean()). 252254721Semaste //---------------------------------------------------------------------- 253254721Semaste void 254254721Semaste set (const value_type value) 255254721Semaste { 256254721Semaste // Cleanup the current value if needed 257254721Semaste clean (); 258254721Semaste // Now set the new value and mark our callback as not called 259254721Semaste m_callback_called = false; 260254721Semaste m_current_value = value; 261254721Semaste } 262254721Semaste 263254721Semaste //---------------------------------------------------------------------- 264254721Semaste // Checks is "m_current_value" is valid. The value is considered valid 265254721Semaste // no invalid value was supplied during construction of this object or 266254721Semaste // if an invalid value was supplied and "m_current_value" is not equal 267254721Semaste // to "m_invalid_value". 268254721Semaste // 269254721Semaste // Returns true if "m_current_value" is valid, false otherwise. 270254721Semaste //---------------------------------------------------------------------- 271254721Semaste bool 272254721Semaste is_valid() const 273254721Semaste { 274254721Semaste if (m_invalid_value_is_valid) 275254721Semaste return m_current_value != m_invalid_value; 276254721Semaste return true; 277254721Semaste } 278254721Semaste 279254721Semaste //---------------------------------------------------------------------- 280254721Semaste // This function will call the cleanup callback provided in the 281254721Semaste // constructor one time if the value is considered valid (See is_valid()). 282254721Semaste // This function sets m_callback_called to true so we don't call the 283254721Semaste // cleanup callback multiple times on the same value. 284254721Semaste //---------------------------------------------------------------------- 285254721Semaste void 286254721Semaste clean() 287254721Semaste { 288254721Semaste if (m_callback && !m_callback_called) 289254721Semaste { 290254721Semaste m_callback_called = true; 291254721Semaste if (is_valid()) 292254721Semaste m_callback(m_current_value, m_argument); 293254721Semaste } 294254721Semaste } 295254721Semaste 296254721Semaste //---------------------------------------------------------------------- 297254721Semaste // Cancels the cleanup that would have been called on "m_current_value" 298254721Semaste // if it was valid. This function can be used to release the value 299254721Semaste // contained in this object so ownership can be transfered to the caller. 300254721Semaste //---------------------------------------------------------------------- 301254721Semaste value_type 302254721Semaste release () 303254721Semaste { 304254721Semaste m_callback_called = true; 305254721Semaste return m_current_value; 306254721Semaste } 307254721Semaste 308254721Semasteprivate: 309254721Semaste value_type m_current_value; 310254721Semaste const value_type m_invalid_value; 311254721Semaste CallbackType m_callback; 312254721Semaste bool m_callback_called; 313254721Semaste bool m_invalid_value_is_valid; 314254721Semaste A0 m_argument; 315254721Semaste 316254721Semaste // Outlaw default constructor, copy constructor and the assignment operator 317254721Semaste DISALLOW_COPY_AND_ASSIGN (CleanUp2); 318254721Semaste}; 319254721Semaste 320254721Semaste} // namespace lldb_utility 321254721Semaste 322254721Semaste#endif // #ifndef liblldb_CleanUp_h_ 323