CMS 3D CMS Logo

Handle.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_Handle_h
00002 #define DataFormats_Common_Handle_h
00003 
00004 /*----------------------------------------------------------------------
00005   
00006 Handle: Non-owning "smart pointer" for reference to EDProducts and
00007 their Provenances.
00008 
00009 This is a very preliminary version, and lacks safety features and
00010 elegance.
00011 
00012 If the pointed-to EDProduct or Provenance is destroyed, use of the
00013 Handle becomes undefined. There is no way to query the Handle to
00014 discover if this has happened.
00015 
00016 Handles can have:
00017   -- Product and Provenance pointers both null;
00018   -- Both pointers valid
00019 
00020 To check validity, one can use the isValid() function.
00021 
00022 If failedToGet() returns true then the requested data is not available
00023 If failedToGet() returns false but isValid() is also false then no attempt 
00024   to get data has occurred
00025 
00026 ----------------------------------------------------------------------*/
00027 
00028 #include <typeinfo>
00029 
00030 #include "DataFormats/Provenance/interface/ProductID.h"
00031 #include "DataFormats/Common/interface/BasicHandle.h"
00032 #include "FWCore/Utilities/interface/EDMException.h"
00033 
00034 namespace edm
00035 {
00036   class EDProduct;
00037   template <typename T> class Wrapper;
00038 
00039   template <typename T>
00040   class Handle
00041   {
00042   public:
00043     typedef T element_type;
00044 
00045     // Default constructed handles are invalid.
00046     Handle();
00047 
00048     Handle(const Handle<T>& h);
00049 
00050     Handle(T const* prod, Provenance const* prov);
00051     
00052     Handle(const boost::shared_ptr<cms::Exception>&);
00053 
00054     ~Handle();
00055 
00056     void swap(Handle<T>& other);
00057 
00058     
00059     Handle<T>& operator=(const Handle<T>& rhs);
00060 
00061     bool isValid() const;
00062 
00064     bool failedToGet() const;
00065 
00066     T const* product() const;
00067     T const* operator->() const; // alias for product()
00068     T const& operator*() const;
00069 
00070     Provenance const* provenance() const;
00071 
00072     ProductID id() const;
00073 
00074     void clear();
00075 
00076   private:
00077     T const* prod_;
00078     Provenance const* prov_;    
00079     ProductID id_;
00080     boost::shared_ptr<cms::Exception> whyFailed_;
00081   };
00082 
00083   template <class T>
00084   Handle<T>::Handle() :
00085     prod_(0),
00086     prov_(0),
00087     id_(0)
00088   { }
00089 
00090   template <class T>
00091   Handle<T>::Handle(const Handle<T>& h) :
00092     prod_(h.prod_),
00093     prov_(h.prov_),
00094     id_(h.id_),
00095     whyFailed_(h.whyFailed_)
00096   { }
00097 
00098   template <class T>
00099   Handle<T>::Handle(T const* prod, Provenance const* prov) :
00100     prod_(prod),
00101     prov_(prov),
00102     id_(prov->productID())
00103   { 
00104       assert(prod_);
00105       assert(prov_);
00106   }
00107 
00108   template <class T>
00109     Handle<T>::Handle(const boost::shared_ptr<cms::Exception>& iWhyFailed):
00110     prod_(0),
00111     prov_(0),
00112     id_(0),
00113     whyFailed_(iWhyFailed)
00114   { }
00115 
00116   template <class T>
00117   Handle<T>::~Handle()
00118   { 
00119     // Really nothing to do -- we do not own the things to which we
00120     // point.  For help in debugging, we clear the data.
00121     clear();
00122   }
00123 
00124   template <class T>
00125   void
00126   Handle<T>::swap(Handle<T>& other)
00127   {
00128     using std::swap;
00129     std::swap(prod_, other.prod_);
00130     std::swap(prov_, other.prov_);
00131     swap(id_, other.id_);
00132     swap(whyFailed_,other.whyFailed_);
00133   }
00134 
00135   template <class T>
00136   Handle<T>&
00137   Handle<T>::operator=(const Handle<T>& rhs)
00138   {
00139     Handle<T> temp(rhs);
00140     this->swap(temp);
00141     return *this;
00142   }
00143 
00144   template <class T>
00145   bool
00146   Handle<T>::isValid() const
00147   {
00148     return prod_ != 0 && prov_ != 0;
00149   }
00150 
00151   template <class T>
00152   bool
00153   Handle<T>::failedToGet() const
00154   {
00155     return 0 != whyFailed_.get();
00156   }
00157   
00158   template <class T>
00159   T const* 
00160   Handle<T>::product() const
00161   {
00162     if(failedToGet()) {
00163       throw *whyFailed_;
00164     }
00165     // Should we throw if the pointer is null?
00166     return prod_;
00167   }
00168 
00169   template <class T>
00170   T const* 
00171   Handle<T>::operator->() const
00172   {
00173     return product();
00174   }
00175 
00176   template <class T>
00177   T const& 
00178   Handle<T>::operator*() const
00179   {
00180     return *product();
00181   }
00182 
00183   template <class T>
00184   Provenance const* 
00185   Handle<T>::provenance() const
00186   {
00187     // Should we throw if the pointer is null?
00188     return prov_;
00189   }
00190 
00191   template <class T>
00192   ProductID 
00193   Handle<T>::id() const
00194   {
00195     return id_;
00196   }
00197 
00198   template <class T>
00199   void
00200   Handle<T>::clear()
00201   {
00202     prod_ = 0;
00203     prov_ = 0;
00204     id_ = ProductID();
00205     whyFailed_.reset();
00206   }
00207   //------------------------------------------------------------
00208   // Non-member functions
00209   //
00210 
00211   // Free swap function
00212   template <class T>
00213   inline
00214   void
00215   swap(Handle<T>& a, Handle<T>& b) 
00216   {
00217     a.swap(b);
00218   }
00219 
00220   // Convert from handle-to-EDProduct to handle-to-T
00221   template <class T>
00222   void convert_handle(BasicHandle const& orig,
00223                       Handle<T>& result)
00224   {
00225     if(orig.failedToGet()) {
00226       Handle<T> h(orig.whyFailed());
00227       h.swap(result);
00228       return;
00229     }
00230     EDProduct const* originalWrap = orig.wrapper();
00231     if (originalWrap == 0)
00232       throw edm::Exception(edm::errors::InvalidReference,"NullPointer")
00233       << "edm::BasicHandle has null pointer to Wrapper";
00234     Wrapper<T> const* wrap = dynamic_cast<Wrapper<T> const*>(originalWrap);
00235     if (wrap == 0)
00236       throw edm::Exception(edm::errors::LogicError,"ConvertType")
00237       << "edm::Wrapper converting from EDProduct to "
00238       << typeid(*originalWrap).name();
00239 
00240     Handle<T> h(wrap->product(), orig.provenance());
00241     h.swap(result);
00242   }
00243 
00244 }
00245 
00246 #endif

Generated on Tue Jun 9 17:29:03 2009 for CMSSW by  doxygen 1.5.4