00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef RESOURCE_H 00011 #define RESOURCE_H 00012 00013 #include <cstdlib> 00014 00015 /** 00016 * The MemoryObject is a trait object for use with the Resource template. It provides capability for creating and 00017 * deleting objects from the local heap. A Resource using this trait behaves the same as an auto_ptr. This is the 00018 * default trait used if a Resource object is declared without specifying the trait class. 00019 */ 00020 template<class T> 00021 class MemoryObject 00022 { 00023 public: 00024 class Args {}; 00025 T* obtainResource(const Args& args) const 00026 { 00027 return new T; 00028 } 00029 00030 void releaseResource(const Args& args, T* pObject) const 00031 { 00032 delete pObject; 00033 } 00034 }; 00035 00036 /** 00037 * This is the basic template that underlies all of the Resource capability. 00038 * 00039 * The Resource template is effectively an auto_ptr with a trait describing how to obtain and release 00040 * the resource. The default trait is MemoryObject, which results in identical syntax and functionality 00041 * to an auto_ptr. It can also be used to manage FILE *, objects and vectors created via the Object 00042 * Factory and spectral elements created via ModelServices. The following examples show creation 00043 * (and upon exit from the code block - destruction) of each of these types. 00044 * 00045 * @code 00046 * { 00047 * // Allocate a PassThru object from the heap. The PassThru object will be deleted on destruction of the Resource 00048 * Resource<struct PassThru> pMyObject; 00049 * Resource<struct PassThru> pMyObject2(new PassThru); // alternate syntax to the above line 00050 * 00051 * // Open a file for reading. On destruction of the FileResource, the file will be closed 00052 * Resource<FILE,FileObject> pMyFile(FileObject::Args("e:\\application\\configure.in", "r")); 00053 * FileResource pMyFile2(FileObject::Args("e:\\application\\configure", "r")); // alternate syntax to the above line 00054 * FileResource pMyFile3("e:\\application\\configure.out", "r"); // alternate syntax to the above line 00055 * 00056 * // Create a Filename object via the ObjectFactory. On destruction of the FactoryResource, the 00057 * // object will be destroyed via the ObjectFactory. 00058 * Resource<Filename,FactoryObject> pMyFilename(FactoryArgs("Filename")); 00059 * FactoryResource<Filename> pMyFilename2(); // alternate syntax to the above line 00060 * 00061 * // Create an empty vector of Filename objects via the ObjectFactory. 00062 * Resource<vector<Filename*>,FactoryVector> pMyVector(FactoryArgs("Filename")); 00063 * 00064 * // Create a DataElement via ModelServices. On destruction of the ModelResource, the 00065 * // object will be destroyed via ModelServices. 00066 * ModelResource<AoiElement> pMyAoi2("MyAoi", mpRasterElement); 00067 * } // closes all 3 files and deletes the Filename, vector, AOI, and PassThru objects 00068 * @endcode 00069 * 00070 * Additional traits can be defined as needed. The requirements for a traits class are as follows. 00071 * 1) It must have a default constructor 00072 * 2) It must define a nested struct/class/typedef called Args 00073 * 3) It must define a method called obtainResource taking an Args object as its only non-default argument and 00074 * returning a value that can be cast to a (T*). If this call fails, the obtainResource method should throw an 00075 * exception to prevent the creation of an invalid Resource object. 00076 * 4) It must define a method called releaseResource taking an Args object and a T* as its only non-default arguments 00077 * The only requirement on the nested 'Args' struct/class is that it have a copy constructor. 00078 * 00079 * @param T 00080 * The type of the object the Resource wraps 00081 * @param SourceTrait 00082 * The type of object to use for obtaining and releasing objects of type T 00083 */ 00084 template <class T, class SourceTrait = MemoryObject<T> > 00085 class Resource 00086 { 00087 protected: 00088 typedef typename SourceTrait::Args Args; 00089 00090 public: 00091 /** 00092 * Constructs the Resource object. 00093 * 00094 * Constructs the Resource object by storing the args and by calling obtainResource 00095 * on the SourceTrait. If no argument is provided, it will construct the Resource using 00096 * the SourceTrait's default Args object. 00097 * 00098 * @param args 00099 * The arguments that will be provided to the obtainResource method of the SourceTrait. The type 00100 * of this argument is dependent on the SourceTrait. 00101 */ 00102 explicit Resource(const Args& args = Args()) : 00103 mArgs(args), 00104 mOwns(true), 00105 mpObject(static_cast<T*>(SourceTrait().obtainResource(args))) {} 00106 00107 /** 00108 * Constructs the Resource object. 00109 * 00110 * Constructs the Resource object based on an existing object. Essentially, this wraps the object 00111 * in the Resource and assigns the Resource object the responsibility for freeing the underlying object. 00112 * 00113 * @param pObject 00114 * The object to wrap in the Resource. 00115 * @param args 00116 * The arguments that would have been provided to the obtainResource method of the SourceTrait. The type 00117 * of this argument is dependent on the SourceTrait. 00118 */ 00119 explicit Resource(T* pObject, const Args& args = Args()) : 00120 mArgs(args), 00121 mOwns(true), 00122 mpObject(pObject) {} 00123 00124 /** 00125 * Copy-constructs the Resource object. 00126 * 00127 * Copy-constructs a Resource object from an existing Resource object. The new Resource object 00128 * takes ownership of the wrapped object from the source object. 00129 * 00130 * @param source 00131 * The Resource object to construct from. After this call, the source no longer owns the wrapped object. 00132 */ 00133 Resource(const Resource<T, SourceTrait>& source) : 00134 mArgs(source.mArgs), 00135 mOwns(source.mOwns), 00136 mpObject(const_cast<T*>(source.release())) {} 00137 00138 /** 00139 * Sets a Resource object to another one. 00140 * 00141 * The assigned object takes ownership of the wrapped object from the 00142 * source object. 00143 * 00144 * @param source 00145 * The Resource object to assign from. After this call, the source no longer owns the wrapped object. 00146 */ 00147 Resource<T, SourceTrait>& operator=(const Resource<T, SourceTrait>& source) 00148 { 00149 if (this != &source) 00150 { 00151 if (mpObject != source.get()) 00152 { 00153 destroyIfOwned(); 00154 mOwns = source.mOwns; 00155 } 00156 else if (source.mOwns) 00157 { 00158 mOwns = true; 00159 } 00160 mpObject = const_cast<T*>(source.release()); 00161 mArgs = source.mArgs; 00162 } 00163 return *this; 00164 } 00165 00166 /** 00167 * Destructs a %Resource object. 00168 * 00169 * If the %Resource object owns the wrapped object, the wrapped object will 00170 * be freed via the SourceTrait's releaseResource method. 00171 */ 00172 virtual ~Resource() 00173 { 00174 destroyIfOwned(); 00175 } 00176 00177 /** 00178 * Gets the args that were used when the %Resource was created. 00179 * 00180 * @return The args that were used when the %Resource was created. 00181 */ 00182 const Args& getArgs() const 00183 { 00184 return mArgs; 00185 } 00186 00187 /** 00188 * Gets the args that were used when the %Resource was created. 00189 * 00190 * @return The args that were used when the %Resource was created. 00191 */ 00192 Args& getArgs() 00193 { 00194 return mArgs; 00195 } 00196 00197 /** 00198 * Gets a pointer to the underlying object. 00199 * 00200 * @return A pointer to the underlying object. 00201 */ 00202 const T* get() const 00203 { 00204 return mpObject; 00205 } 00206 00207 /** 00208 * Gets a pointer to the underlying object. 00209 * 00210 * @return A pointer to the underlying object. 00211 */ 00212 T* get() 00213 { 00214 return mpObject; 00215 } 00216 00217 /** 00218 * Gets a pointer to the underlying object. 00219 * 00220 * @return A pointer to the underlying object. 00221 */ 00222 const T* operator->() const 00223 { 00224 return get(); 00225 } 00226 00227 /** 00228 * Gets a pointer to the underlying object. 00229 * 00230 * @return A pointer to the underlying object. 00231 */ 00232 T* operator->() 00233 { 00234 return get(); 00235 } 00236 00237 /** 00238 * Gets a reference to the underlying object. 00239 * 00240 * @return A reference to the underlying object. 00241 */ 00242 const T& operator*() const 00243 { 00244 return *get(); 00245 } 00246 00247 /** 00248 * Gets a reference to the underlying object. 00249 * 00250 * @return A reference to the underlying object. 00251 */ 00252 T& operator*() 00253 { 00254 return *get(); 00255 } 00256 00257 /** 00258 * Returns a reference to the indexed object. 00259 * 00260 * Indexes into the underlying array and returns a 00261 * reference to the indexed object. This is only useful 00262 * if the SourceTrait's obtainResource and releaseResource 00263 * work with arrays of objects. In other cases, calling 00264 * this method with an index of other than 0 will cause 00265 * undefined behavior. 00266 * 00267 * @param index 00268 * The index of the object in the underlying array. 00269 * 00270 * @return A reference to the underlying indexed object. 00271 */ 00272 const T& operator[](int index) const 00273 { 00274 return get()[index]; 00275 } 00276 00277 /** 00278 * Returns a reference to the indexed object. 00279 * 00280 * Indexes into the underlying array and returns a 00281 * reference to the indexed object. This is only useful 00282 * if the SourceTrait's obtainResource and releaseResource 00283 * work with arrays of objects. In other cases, calling 00284 * this method with an index of other than 0 will cause 00285 * undefined behavior. 00286 * 00287 * @param index 00288 * The index of the object in the underlying array. 00289 * 00290 * @return A reference to the underlying indexed object. 00291 */ 00292 T& operator[](int index) 00293 { 00294 return get()[index]; 00295 } 00296 00297 /** 00298 * Removes ownership of the underlying resource and returns it. 00299 * 00300 * Gets a pointer to the underlying object and removes 00301 * ownership of the underlying object. After this call, the 00302 * %Resource object no longer owns the underlying object. 00303 * 00304 * @return A pointer to the underlying object. 00305 */ 00306 const T* release() const 00307 { 00308 mOwns = false; 00309 return get(); 00310 } 00311 00312 /** 00313 * Removes ownership of the underlying resource and returns it. 00314 * 00315 * Gets a pointer to the underlying object and removes 00316 * ownership of the underlying object. After this call, the 00317 * %Resource object no longer owns the underlying object. 00318 * 00319 * @return A pointer to the underlying object. 00320 */ 00321 T* release() 00322 { 00323 mOwns = false; 00324 return get(); 00325 } 00326 00327 protected: 00328 /** 00329 * Destroys the underlying resource. 00330 * 00331 * If the underlying object is owned by the %Resource, this 00332 * method destroys it via the SourceTrait's releaseResource 00333 * method. After destroying it, the %Resource object is empty. 00334 */ 00335 void destroyIfOwned() 00336 { 00337 if (mpObject != NULL && mOwns) 00338 { 00339 SourceTrait().releaseResource(mArgs, mpObject); 00340 mpObject = NULL; 00341 mOwns = false; 00342 } 00343 } 00344 00345 private: 00346 Args mArgs; 00347 mutable bool mOwns; 00348 T* mpObject; 00349 }; 00350 00351 /** 00352 * RAII object to reset a variable. 00353 */ 00354 template<typename T> 00355 class ResetVariableOnDestroy 00356 { 00357 public: 00358 /** 00359 * Construct the object. 00360 * 00361 * @param variable 00362 * The variable to reset to its initial value. 00363 * 00364 * @param value 00365 * The value to put in the variable until destruction. 00366 */ 00367 ResetVariableOnDestroy(T& variable, const T& value) : 00368 mVariable(variable), 00369 mOriginalValue(variable) 00370 { 00371 mVariable = value; 00372 } 00373 00374 /** 00375 * Reset the initial value in the variable. 00376 */ 00377 ~ResetVariableOnDestroy() 00378 { 00379 mVariable = mOriginalValue; 00380 } 00381 00382 private: 00383 ResetVariableOnDestroy& operator=(const ResetVariableOnDestroy& rhs); 00384 00385 T& mVariable; 00386 T mOriginalValue; 00387 }; 00388 00389 #endif