AttachmentPtr.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 ATTACHMENTPTR_H
00011 #define ATTACHMENTPTR_H
00012 
00013 #include "SafePtr.h"
00014 
00015 #include <string>
00016 #include <vector>
00017 #include <utility>
00018 
00019 /**
00020  * Smart pointer used to simplify Subject attachment lifetimes.
00021  *
00022  * This class handles a number of issues relating to the management of
00023  * Subject attachment lifetimes:
00024  *   - Detaching from the Subject upon destruction.
00025  *   - Changing attachments when the observed instance changed, including
00026  *     attachments made within subclasses of the observer.
00027  *   - Detecting when the Subject is deleted to prevent stale pointers.
00028  *
00029  * This class is intended to be used as a member variable, in place of a raw
00030  * pointer to the observed Subject.  If subclasses are to be allowed to attach
00031  * to the Subject, the variable should be made protected.
00032  *
00033  * Note that this class will not cause any kind of callback in the case
00034  * that its Subject has been deleted.  It will simply NULLify the pointer.
00035  * If you require any special handling for when the Subject has been deleted,
00036  * You should separately attach to SIGNAL_NAME(Subject, Deleted) with 
00037  * AttachmentPtr::addSignal().
00038  *
00039  * When used in conjunction with a SafeSlot, the attachments will additionally be 
00040  * automatically detached when the SafeSlot's invalidator object is destroyed.
00041  */
00042 template<typename T>
00043 class AttachmentPtr : public SafePtr<T>
00044 {
00045 public:
00046    /**
00047     * Default constructor.
00048     *
00049     * No Subject is observed.
00050     */
00051    AttachmentPtr() : SafePtr<T>(NULL)
00052    {
00053    }
00054 
00055    /**
00056     *  Construct with a subject to observe.
00057     *
00058     *  @param   pSubject
00059     *           The subject to observe.
00060     */
00061    AttachmentPtr(T* pSubject) :
00062       SafePtr<T>(pSubject)
00063    {
00064    }
00065 
00066    /**
00067     * Construct with a single signal/slot connection registered,
00068     * no Subject observed.
00069     *
00070     * @param signalName
00071     *        The signal to register interest in.
00072     * @param slot
00073     *        The slot to call when the signal is emitted.
00074     */
00075    AttachmentPtr(const std::string& signalName, const Slot& slot) : SafePtr<T>(NULL),
00076       mSignalSlots(1, std::make_pair(signalName, slot))
00077    {
00078    }
00079 
00080    /**
00081     * Construct with a subject to observe, and a single signal/slot
00082     * connection registered.
00083     *
00084     * @param pSubject
00085     *        The subject to observe.
00086     * @param signalName
00087     *        The signal to register interest in.
00088     * @param slot
00089     *        The slot to call when the signal is emitted.
00090     */
00091    AttachmentPtr(T* pSubject, const std::string& signalName, const Slot& slot) : SafePtr<T>(pSubject),
00092       mSignalSlots(1, std::make_pair(signalName, slot))
00093    {
00094       SafePtr<T>::attach(signalName, slot);
00095    }
00096 
00097    /**
00098     * Destructor.
00099     *
00100     * This will take care of detaching from any signals.
00101     */
00102    virtual ~AttachmentPtr()
00103    {
00104       reset(NULL);
00105    }
00106 
00107    /**
00108     * Add a new signal to be observed.
00109     *
00110     * The attachment will be made immediately if there is currently a valid
00111     * Subject.  The attachment will automatically be made whenever the
00112     * observed Subject is changed.
00113     *
00114     * @param signalName
00115     *        The signal to register interest in.
00116     * @param slot
00117     *        The slot to call when the signal is emitted.
00118     */
00119    void addSignal(const std::string& signalName, const Slot& slot)
00120    {
00121       mSignalSlots.push_back(std::make_pair(signalName, slot));
00122 
00123       SafePtr<T>::attach(signalName, slot);
00124    }
00125 
00126    /**
00127     * Change what Subject to observe.
00128     *
00129     * This will automatically detach from the old Subject, and attach to
00130     * the new one.
00131     *
00132     * @param pSubject
00133     *        The subject to begin observing.
00134     */
00135    void reset(T* pSubject = NULL)
00136    {
00137       if (pSubject != SafePtr<T>::get())
00138       {
00139          for (std::vector<std::pair<std::string, Slot> >::const_iterator iter = mSignalSlots.begin();
00140             iter != mSignalSlots.end(); ++iter)
00141          {
00142             SafePtr<T>::detach(iter->first, iter->second);
00143          }
00144          SafePtr<T>::reset(pSubject);
00145          for (std::vector<std::pair<std::string, Slot> >::const_iterator iter = mSignalSlots.begin();
00146             iter != mSignalSlots.end(); ++iter)
00147          {
00148             SafePtr<T>::attach(iter->first, iter->second);
00149          }
00150       }
00151    }
00152 
00153 private:
00154    AttachmentPtr(const AttachmentPtr&);
00155    AttachmentPtr& operator=(const AttachmentPtr&);
00156 
00157    std::vector<std::pair<std::string, Slot> > mSignalSlots;
00158 };
00159 
00160 #endif

Software Development Kit - Opticks 4.9.0 Build 16218