Resource.h

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

Software Development Kit - Opticks 4.9.0 Build 16218