SafePtr.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2009 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 SAFE_PTR_H
00011 #define SAFE_PTR_H
00012 
00013 #include "Slot.h"
00014 #include "Subject.h"
00015 
00016 /**
00017  * Smart pointer used to automatically NULLify when the subject is deleted.
00018  *
00019  * This class handles a number of issues relating to the management of
00020  * Subject attachment lifetimes:
00021  *   - Detaching from the Subject upon destruction.
00022  *   - Detecting when the Subject is deleted to prevent stale pointers.
00023  *
00024  * This class is intended to be used as a member variable, in place of a raw
00025  * pointer to the Subject.  If subclasses are to be allowed to attach
00026  * to the Subject, the variable should be made protected.
00027  *
00028  * Note that this class will not cause any kind of callback when
00029  * its Subject has been deleted.  It will simply NULLify the pointer.
00030  * If you require any special handling for when the Subject has been deleted,
00031  * You should separately attach to SIGNAL_NAME(Subject, Deleted).
00032  */
00033 template<typename T>
00034 class SafePtr
00035 {
00036 public:
00037    /**
00038     * Default constructor.
00039     *
00040     * No Subject is observed.
00041     */
00042    SafePtr() : mpSubject(NULL)
00043    {
00044    }
00045 
00046    /**
00047     *  Construct with a subject to observe.
00048     *
00049     *  @param   pSubject
00050     *           The subject to observe.
00051     */
00052    SafePtr(T* pSubject) :
00053       mpSubject(pSubject)
00054    {
00055       attachToDeleted();
00056    }
00057 
00058    /**
00059     * Destructor.
00060     *
00061     * This will take care of detaching from any signals.
00062     */
00063    virtual ~SafePtr()
00064    {
00065       detachFromDeleted();
00066       mpSubject = NULL;
00067    }
00068 
00069    /**
00070     * Change what Subject to observe.
00071     *
00072     * This will automatically detach from the old Subject, and attach to
00073     * the new one.
00074     *
00075     * @param pSubject
00076     *        The subject to begin observing.
00077     */
00078    void reset(T* pSubject = NULL)
00079    {
00080       if (pSubject != mpSubject)
00081       {
00082          detachFromDeleted();
00083          mpSubject = pSubject;
00084          attachToDeleted();
00085       }
00086    }
00087 
00088    /**
00089     * Get the observed Subject.
00090     *
00091     * @return The observed Subject.
00092     */
00093    T* get()
00094    {
00095       return mpSubject;
00096    }
00097 
00098    /**
00099     * @copydoc SafePtr::get()
00100     */
00101    const T* get() const
00102    {
00103       return mpSubject;
00104    }
00105 
00106    /**
00107     * @copydoc SafePtr::get()
00108     */
00109    T* operator->()
00110    {
00111       return get();
00112    }
00113 
00114    /**
00115     * @copydoc SafePtr::get()
00116     */
00117    const T* operator->() const
00118    {
00119       return get();
00120    }
00121 
00122 protected:
00123    /**
00124     * Attaches the specified slot to the specified signal on the current
00125     * Subject. If there is no current Subject, it does nothing.
00126     *
00127     * @param signal
00128     *            The name of the signal to attach to
00129     *
00130     * @param slot
00131     *            The slot to attach to the signal
00132     */
00133    void attach(const std::string& signal, const Slot& slot)
00134    {
00135       if (mpSubject != NULL)
00136       {
00137          mpSubject->attach(signal, slot);
00138       }
00139    }
00140 
00141    /**
00142     * Detaches the specified slot from the specified signal on the current
00143     * Subject. If there is no current Subject, it does nothing.
00144     *
00145     * @param signal
00146     *            The name of the signal to detach from
00147     *
00148     * @param slot
00149     *            The slot to detach from the signal
00150     */
00151    void detach(const std::string& signal, const Slot& slot)
00152    {
00153       if (mpSubject != NULL)
00154       {
00155          mpSubject->detach(signal, slot);
00156       }
00157    }
00158 
00159 private:
00160    SafePtr(const SafePtr&);
00161    SafePtr& operator=(const SafePtr&);
00162 
00163    void attachToDeleted()
00164    {
00165       attach(SIGNAL_NAME(Subject, Deleted), Slot(this, &SafePtr::subjectDeleted));
00166    }
00167 
00168    void detachFromDeleted()
00169    {
00170       detach(SIGNAL_NAME(Subject, Deleted), Slot(this, &SafePtr::subjectDeleted));
00171    }
00172 
00173    void subjectDeleted(Subject& subject, const std::string& signal, const boost::any& data)
00174    {
00175       if (&subject == mpSubject)
00176       {
00177          mpSubject = NULL;
00178       }
00179    }
00180 
00181    T* mpSubject;
00182 };
00183 
00184 #endif

Software Development Kit - Opticks 4.9.0 Build 16218