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