00001 /* $Id: scoped_resource.hpp 23842 2008-02-16 08:47:16Z mordante $ */ 00002 /* 00003 Copyright (C) 2003 - 2008 by David White <dave@whitevine.net> 00004 Part of the Battle for Wesnoth Project http://www.wesnoth.org/ 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License version 2 00008 or at your option any later version. 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY. 00011 00012 See the COPYING file for more details. 00013 */ 00014 00015 //! @file scoped_resource.hpp 00016 //! scoped_resource: class template, functions, helper policies etc.\ for 00017 //! resource management. 00018 00019 #ifndef SCOPED_RESOURCE_H_INCLUDED 00020 #define SCOPED_RESOURCE_H_INCLUDED 00021 00022 #include "global.hpp" 00023 #include <cstdio> //for FILE 00024 00025 namespace util 00026 { 00027 /** 00028 * A class template, scoped_resource, designed to implement 00029 * the Resource Acquisition Is Initialization (RAII) approach 00030 * to resource management. 00031 * scoped_resource is designed to be used when a resource 00032 * is initialized at the beginning or middle of a scope, 00033 * and released at the end of the scope. 00034 * The template argument ReleasePolicy is a functor 00035 * which takes an argument of the type of the resource, 00036 * and releases it. 00037 * 00038 * Usage example, for working with files: 00039 * 00040 * @code 00041 * struct close_file { void operator()(int fd) const {close(fd);} }; 00042 * ... 00043 * { 00044 * const scoped_resource<int,close_file> file(open("file.txt",O_RDONLY)); 00045 * read(file, buf, 1000); 00046 * } // file is automatically closed here 00047 * @endcode 00048 * 00049 * Note that scoped_resource has an explicit constructor, 00050 * and prohibits copy-construction, and thus the initialization syntax. 00051 * The assignment syntax must be used when initializing. 00052 * 00053 * I.e. using scoped_resource<int,close_file> file = open("file.txt",O_RDONLY); 00054 * in the above example is illegal. 00055 * 00056 */ 00057 template<typename T,typename ReleasePolicy> 00058 class scoped_resource 00059 { 00060 T resource; 00061 00062 //prohibited operations 00063 scoped_resource(const scoped_resource&); 00064 scoped_resource& operator=(const scoped_resource&); 00065 public: 00066 typedef T resource_type; 00067 typedef ReleasePolicy release_type; 00068 00069 /** 00070 * Constructor 00071 * 00072 * @param res This is the resource to be managed 00073 */ 00074 scoped_resource(resource_type res = resource_type()) 00075 : resource(res) {} 00076 00077 /** 00078 * The destructor is the main point in this class. 00079 * It takes care of proper deletion of the resource, 00080 * using the provided release policy. 00081 */ 00082 virtual ~scoped_resource() 00083 { 00084 release_type()(resource); 00085 } 00086 00087 /** 00088 * This operator makes sure you can access and use the scoped_resource 00089 * just like you were using the resource itself. 00090 * 00091 * @return the underlying resource 00092 */ 00093 operator resource_type() const { return resource; } 00094 00095 /** 00096 * This function provides explicit access to the resource. 00097 * Its behaviour is identical to operator resource_type() 00098 * 00099 * @return the underlying resource 00100 */ 00101 resource_type get() const { return resource; } 00102 00103 /** 00104 * This function provides convenient direct access to the -> operator 00105 * if the underlying resource is a pointer. 00106 * Only call this function if resource_type is a pointer type. 00107 */ 00108 resource_type operator->() const { return resource; } 00109 00110 void assign(const resource_type& o) { 00111 release_type()(resource); 00112 resource = o; 00113 } 00114 }; 00115 00116 /** 00117 * A helper policy for scoped_ptr. 00118 * It will call the delete operator on a pointer, and assign the pointer to 0 00119 */ 00120 struct delete_item { 00121 template<typename T> 00122 void operator()(T*& p) const { delete p; p = 0; } 00123 }; 00124 /** 00125 * A helper policy for scoped_array. 00126 * It will call the delete[] operator on a pointer, and assign the pointer to 0 00127 */ 00128 struct delete_array { 00129 template<typename T> 00130 void operator()(T*& p) const { delete [] p; p = 0; } 00131 }; 00132 00133 /** 00134 * A class which implements an approximation of 00135 * template<typename T> 00136 * typedef scoped_resource<T*,delete_item> scoped_ptr<T>; 00137 * 00138 * It is a convenient synonym for a common usage of @ref scoped_resource. 00139 * See scoped_resource for more details on how this class behaves. 00140 * 00141 * Usage example: 00142 * @code 00143 * { 00144 * const scoped_ptr<Object> ptr(new Object); 00145 * ...use ptr as you would a normal Object*... 00146 * } // ptr is automatically deleted here 00147 * @endcode 00148 * 00149 * NOTE: use this class only to manage a single object, *never* an array. 00150 * Use scoped_array to manage arrays. 00151 * This distinction is because you may call delete only 00152 * on objects allocated with new, 00153 * delete[] only on objects allocated with new[]. 00154 */ 00155 template<typename T> 00156 struct scoped_ptr : public scoped_resource<T*,delete_item> 00157 { 00158 explicit scoped_ptr(T* p) : scoped_resource<T*,delete_item>(p) {} 00159 }; 00160 00161 /** 00162 * This class has identical behaviour to @ref scoped_ptr, except it 00163 * manages heap-allocated arrays instead of heap-allocated single objects 00164 * 00165 * Usage example: 00166 * @code 00167 * { 00168 * const scoped_array<char> ptr(new char[n]); 00169 * ...use ptr as you would a normal char*... 00170 * } // ptr is automatically deleted here 00171 * @endcode 00172 * 00173 */ 00174 template<typename T> 00175 struct scoped_array : public scoped_resource<T*,delete_array> 00176 { 00177 explicit scoped_array(T* p) : scoped_resource<T*,delete_array>(p) {} 00178 }; 00179 00180 /** 00181 * This class specializes the scoped_resource to implement scoped FILEs. 00182 * Not sure this is the best place to place such an utility, though. 00183 */ 00184 struct close_FILE 00185 { 00186 void operator()(std::FILE* f) const { if(f != NULL) { std::fclose(f); } } 00187 }; 00188 typedef scoped_resource<std::FILE*,close_FILE> scoped_FILE; 00189 00190 } 00191 00192 #endif
Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth | Gna! | Forum | Wiki | CIA | devdocs |