SundanceHandle.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // **********************************************************************/
00027  /* @HEADER@ */
00028 
00029 #ifndef SundanceHANDLE_HPP
00030 #define SundanceHANDLE_HPP
00031 
00032 #include "SundanceDefs.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "SundancePrintable.hpp"
00035 #include "Teuchos_Describable.hpp"
00036 #include "SundanceHandleable.hpp"
00037 #include "SundanceNamedObject.hpp"
00038 #include "SundanceObjectWithVerbosity.hpp"
00039 #include "Teuchos_RefCountPtr.hpp"
00040 #include "Teuchos_TypeNameTraits.hpp"
00041 
00042 
00043  /** \def This helper macro defines boilerplate constructors for classes deriving
00044   * from Handle.
00045   *
00046   * If class MyHandle is a handle to a type MyType, simply 
00047   * put
00048   * \code
00049   * HANDLE_CTORS(MyHandle, MyType);
00050   * \endcode
00051   * in the class declaration of MyHandle and the macro will create 
00052   * an empty ctor, a ctor from a smart ptr, and a ctor from a raw pointer. 
00053   * The macro will also create appropriate doxygen for the handle ctors */
00054 #define HANDLE_CTORS(handle, contents) \
00055   /** Empty ctor */ \
00056 handle() : Sundance::Handle<contents >() {;} \
00057   /** Construct a #handle with a raw pointer to a #contents */ \
00058   handle(Sundance::Handleable<contents >* rawPtr) : Sundance::Handle<contents >(rawPtr) {;} \
00059   /** Construct a #handle with a smart pointer to a #contents */ \
00060   handle(const Teuchos::RCP<contents >& smartPtr) : Sundance::Handle<contents >(smartPtr){;}
00061 
00062 
00063 
00064 
00065 
00066 namespace Sundance
00067 {
00068 using namespace Teuchos;
00069 
00070 /** This traits class is used to extract the non-const version of
00071  * a template argument. The generic case returns the template argument. */
00072 template <class X>
00073 class ConstHandleTraits
00074 {
00075 public:
00076   typedef X NonconstType;
00077 };
00078 
00079 
00080 /** Specialization of CHT to types "const X". The nonconst type can
00081  * be extracted from the template argument. */
00082 template <class X>
00083 class ConstHandleTraits<const X>
00084 {
00085 public:
00086   typedef X NonconstType;
00087 };
00088 
00089 
00090 /**
00091  * Class Sundance::Handle provides a general implementation
00092  * of the common features of reference-counted handles.
00093  */
00094 template <class PointerType>
00095 class Handle : public ObjectWithVerbosityBase
00096 {
00097 public:
00098   /** Empty ctor  */
00099   Handle() : ptr_() {;}
00100 
00101   /** Construct from a smart pointer */
00102   Handle(const RCP<PointerType>& _ptr) : ptr_(_ptr) {;}
00103 
00104   /** Construct from a raw pointer to a Handleable.  */
00105   Handle(Handleable<PointerType>* rawPtr) : ptr_(rawPtr->getRcp()) {;}
00106 
00107   /** Read-only access to the underlying smart pointer. */
00108   const RCP<PointerType>& ptr() const {return ptr_;}
00109 
00110   /** Read-write access to the underlying smart pointer. */
00111   RCP<PointerType>& ptr() {return ptr_;}
00112 
00113   /** 
00114    * Print to a stream using the Printable interface. 
00115    * If the contents of the handle cannot be 
00116    * downcasted or crosscasted to a Printable*, an exception
00117    * will be thrown 
00118    */
00119   void print(std::ostream& os) const ;
00120 
00121 
00122   /** 
00123    * Return a short descriptive std::string using the Describable interface.
00124    * If the contents of the handle cannot be 
00125    * downcasted or crosscasted to a Describable*, an exception
00126    * will be thrown. 
00127    */
00128   std::string description() const ;
00129 
00130   /** */
00131   void setName(const std::string& name)
00132     {
00133       NamedObject* n = dynamic_cast<NamedObject*>(ptr_.get());
00134       if (n!=0) n->setName(name);
00135     }
00136 
00137   /** */
00138   std::string name() const 
00139     {
00140       NamedObject* n = dynamic_cast<NamedObject*>(ptr_.get());
00141       if (n!=0) return n->name();
00142       return "AnonymousHandle";
00143     }
00144 
00145   /** 
00146    * Return the verbosity setting using the ObjectWithVerbosity
00147    * interface. If the contents of the handle cannot be downcasted
00148    * or crosscasted into an ObjectWithVerbosity, a value of
00149    * zero will be returned.
00150    */
00151   int verb() const 
00152     {
00153       const ObjectWithVerbosityBase* v 
00154         = dynamic_cast<const ObjectWithVerbosityBase*>(ptr_.get());
00155         
00156       if (v) return v->verb();
00157       return 0;
00158     }
00159 
00160   /** 
00161    * Set the verbosity level of the object using the  ObjectWithVerbosity
00162    * interface. If the contents of the handle cannot be downcasted
00163    * or crosscasted into an ObjectWithVerbosity, this call will be
00164    * ignored and a warning printed.
00165    */
00166   void setVerbosity(int x) 
00167     {
00168       /* Hack warning: this is a trick to deal with the case where
00169        * PointerType is const, e.g., someone has written a RCP<const X>. 
00170        * In such a case the cast to a non-const OWVB would fail. 
00171        * The ConstHandleTraits business lets us extract the underlying type
00172        * (e.g., X) with which we can do a const cast. */
00173       typedef typename ConstHandleTraits<PointerType>::NonconstType NC;
00174       NC* p = const_cast<NC*>(ptr_.get());
00175       ObjectWithVerbosityBase* v 
00176         = dynamic_cast<ObjectWithVerbosityBase*>(p);
00177 
00178       if (v) v->setVerbosity(x);
00179       else
00180       {
00181         Out::os() << "WARNING: cannot set verbosity of object=";
00182         this->print(Out::os());
00183         Out::os() << std::endl;
00184       }
00185     }
00186 
00187   /** Write a fallback description to be used in objects that are
00188    * neither named, printable, or describable */
00189   std::string fallbackDescription() const ;
00190 
00191 private:
00192   RCP<PointerType> ptr_;
00193 };
00194 
00195 /* implementation of print() */
00196 template <class PointerType> inline 
00197 void Handle<PointerType>::print(std::ostream& os) const 
00198 {
00199   const NamedObject* n = dynamic_cast<const NamedObject*>(ptr_.get());
00200   const Printable* p = dynamic_cast<const Printable*>(ptr_.get());
00201   const Describable* d = dynamic_cast<const Describable*>(ptr_.get());
00202   const ObjectWithVerbosityBase* v 
00203     = dynamic_cast<const ObjectWithVerbosityBase*>(ptr_.get());
00204 
00205   if (v != 0)
00206   {
00207     if (v->verb() == 0) 
00208     {
00209       if (n) os << n->name();
00210       else if (d) os << d->description();
00211       else if (p) p->print(os);
00212       else os << fallbackDescription();
00213     }
00214     else if (v->verb()==1)
00215     {
00216       if (d) os << d->description();
00217       else if (p) p->print(os);
00218       else os << fallbackDescription();
00219     }
00220     else
00221     {
00222       if (p) p->print(os);
00223       else os << fallbackDescription();
00224     }
00225   }
00226   else
00227   {
00228     if (p!=0) p->print(os);
00229     else if (d!=0) os << d->description();
00230     else if (n!=0) os << n->name();
00231     else os << fallbackDescription();
00232   }
00233 }
00234 
00235 /* implementation of description() */
00236 template <class PointerType> inline
00237 std::string Handle<PointerType>::description() const 
00238 {
00239   const Describable* d = dynamic_cast<const Describable*>(ptr_.get());
00240   const NamedObject* n = dynamic_cast<const NamedObject*>(ptr_.get());
00241   const ObjectWithVerbosityBase* v 
00242     = dynamic_cast<const ObjectWithVerbosityBase*>(ptr_.get());
00243   TeuchosOStringStream oss;
00244 
00245   if (v != 0)
00246   {
00247     if (v->verb() == 0) 
00248     {
00249       if (n) oss << n->name();
00250       else if (d) oss << d->description();
00251       else oss << fallbackDescription();
00252     }
00253     else
00254     {
00255       if (d) oss << d->description();
00256       else oss << fallbackDescription();
00257     }
00258   }
00259   else
00260   {
00261     if (d!=0) oss << d->description();
00262     else if (n!=0) oss << n->name();
00263     else oss << fallbackDescription();
00264   }
00265   return oss.str();
00266 }
00267 
00268 template <class PointerType> inline
00269 std::string Handle<PointerType>::fallbackDescription() const
00270 {
00271   typedef typename ConstHandleTraits<PointerType>::NonconstType NC;
00272   TeuchosOStringStream oss;
00273 
00274   oss << "Handle[" << TypeNameTraits<NC>::name()
00275       << ", ptr=" << ptr_.get() << "]";
00276   return oss.str();
00277 }
00278 
00279 
00280 
00281 template <class PointerType> inline
00282 std::ostream& operator<<(std::ostream& os, const Sundance::Handle<PointerType>& h)
00283 {
00284   h.print(os);
00285   return os;
00286 }
00287 
00288 }
00289 
00290 #define STREAM_OUT(handleType) \
00291                         inline std::ostream& operator<<(std::ostream& os, const handleType& h) \
00292                         {h.print(os); return os;}
00293 
00294 
00295 
00296 #endif
00297 

Site Contact