scoped_resource.hpp

Go to the documentation of this file.
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