Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_RCPNode.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef TEUCHOS_RCP_NODE_HPP
43 #define TEUCHOS_RCP_NODE_HPP
44 
45 
52 #include "Teuchos_ConfigDefs.hpp"
53 #include "Teuchos_any.hpp"
54 #include "Teuchos_map.hpp"
55 #include "Teuchos_ENull.hpp"
56 #include "Teuchos_Assert.hpp"
57 #include "Teuchos_Exceptions.hpp"
59 #include "Teuchos_toString.hpp"
60 #include "Teuchos_getBaseObjVoidPtr.hpp"
61 
62 
63 namespace Teuchos {
64 
65 
70 enum EPrePostDestruction { PRE_DESTROY, POST_DESTROY };
71 
76 enum ERCPStrength { RCP_STRONG=0, RCP_WEAK=1 };
77 
82 enum ERCPNodeLookup { RCP_ENABLE_NODE_LOOKUP, RCP_DISABLE_NODE_LOOKUP };
83 
85 inline void debugAssertStrength(ERCPStrength strength)
86 {
87 #ifdef TEUCHOS_DEBUG
88  switch (strength) {
89  case RCP_STRONG:
90  // fall through
91  case RCP_WEAK:
92  return; // Fine
93  default:
95  true, std::logic_error, "Teuchos::RCPNode: ERCPStrength enum value "
96  << strength << " is invalid (neither RCP_STRONG = " << RCP_STRONG
97  << " nor RCP_WEAK = " << RCP_WEAK << ").");
98  }
99 #else
100  (void) strength; // Silence "unused variable" compiler warning.
101 #endif // TEUCHOS_DEBUG
102 }
103 
109 template<>
110 class TEUCHOSCORE_LIB_DLL_EXPORT ToStringTraits<ERCPStrength> {
111 public:
112  static std::string toString( const ERCPStrength &t )
113  {
114  switch (t) {
115  case RCP_STRONG:
116  return "RCP_STRONG";
117  case RCP_WEAK:
118  return "RCP_WEAK";
119  default:
120  // Should never get here but fall through ...
121  break;
122  }
123  // Should never get here!
124 #ifdef TEUCHOS_DEBUG
126 #else
127  return "";
128 #endif
129  }
130 };
131 
132 
144 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNode {
145 public:
147  RCPNode(bool has_ownership_in)
148  : has_ownership_(has_ownership_in), extra_data_map_(NULL)
149 #ifdef TEUCHOS_DEBUG
150  ,insertion_number_(-1)
151 #endif // TEUCHOS_DEBUG
152  {
153  count_[RCP_STRONG] = 0;
154  count_[RCP_WEAK] = 0;
155  }
157  virtual ~RCPNode()
158  {
159  if(extra_data_map_)
160  delete extra_data_map_;
161  }
163  int strong_count() const
164  {
165  return count_[RCP_STRONG];
166  }
168  int weak_count() const
169  {
170  return count_[RCP_WEAK];
171  }
173  int incr_count( const ERCPStrength strength )
174  {
175  debugAssertStrength(strength);
176  return ++count_[strength];
177  }
179  int deincr_count( const ERCPStrength strength )
180  {
181  debugAssertStrength(strength);
182  return --count_[strength];
183  }
185  void has_ownership(bool has_ownership_in)
186  {
187  has_ownership_ = has_ownership_in;
188  }
190  bool has_ownership() const
191  {
192  return has_ownership_;
193  }
195  void set_extra_data(
196  const any &extra_data, const std::string& name,
197  EPrePostDestruction destroy_when, bool force_unique );
199  any& get_extra_data( const std::string& type_name,
200  const std::string& name );
202  const any& get_extra_data( const std::string& type_name,
203  const std::string& name
204  ) const
205  {
206  return const_cast<RCPNode*>(this)->get_extra_data(type_name, name);
207  }
209  any* get_optional_extra_data(const std::string& type_name,
210  const std::string& name );
213  const std::string& type_name, const std::string& name
214  ) const
215  {
216  return const_cast<RCPNode*>(this)->get_optional_extra_data(type_name, name);
217  }
219  virtual bool is_valid_ptr() const = 0;
221  virtual void delete_obj() = 0;
223  virtual void throw_invalid_obj_exception(
224  const std::string& rcp_type_name,
225  const void* rcp_ptr,
226  const RCPNode* rcp_node_ptr,
227  const void* rcp_obj_ptr
228  ) const = 0;
230  virtual const std::string get_base_obj_type_name() const = 0;
231 #ifdef TEUCHOS_DEBUG
232 
233  virtual const void* get_base_obj_map_key_void_ptr() const = 0;
234 #endif
235 protected:
238  {
239  if(extra_data_map_)
240  impl_pre_delete_extra_data();
241  }
242 private:
243  struct extra_data_entry_t {
244  extra_data_entry_t() : destroy_when(POST_DESTROY) {}
245  extra_data_entry_t( const any &_extra_data, EPrePostDestruction _destroy_when )
246  : extra_data(_extra_data), destroy_when(_destroy_when)
247  {}
248  any extra_data;
249  EPrePostDestruction destroy_when;
250  };
251  typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
252  int count_[2];
253  bool has_ownership_;
254  extra_data_map_t *extra_data_map_;
255  // Above is made a pointer to reduce overhead for the general case when this
256  // is not used. However, this adds just a little bit to the overhead when
257  // it is used.
258  // Provides the "basic" guarantee!
259  void impl_pre_delete_extra_data();
260  // Not defined and not to be called
261  RCPNode();
262  RCPNode(const RCPNode&);
263  RCPNode& operator=(const RCPNode&);
264 #ifdef TEUCHOS_DEBUG
265  int insertion_number_;
266 public:
267  void set_insertion_number(int insertion_number_in)
268  {
269  insertion_number_ = insertion_number_in;
270  }
271  int insertion_number() const
272  {
273  return insertion_number_;
274  }
275 #endif // TEUCHOS_DEBUG
276 };
277 
278 
283 TEUCHOSCORE_LIB_DLL_EXPORT void throw_null_ptr_error( const std::string &type_name );
284 
285 
302 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeTracer {
303 public:
304 
307 
311  : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
312  totalNumRCPNodeDeletions(0)
313  {}
314  long int maxNumRCPNodes;
315  long int totalNumRCPNodeAllocations;
316  long int totalNumRCPNodeDeletions;
317  };
318 
320 
323 
329  static bool isTracingActiveRCPNodes();
330 
331 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
332 
349  static void setTracingActiveRCPNodes(bool tracingActiveNodes);
350 #endif
351 
355  static int numActiveRCPNodes();
356 
358  static RCPNodeStatistics getRCPNodeStatistics() ;
359 
361  static void printRCPNodeStatistics(
362  const RCPNodeStatistics& rcpNodeStatistics, std::ostream &out);
363 
367  static void setPrintRCPNodeStatisticsOnExit(
368  bool printRCPNodeStatisticsOnExit);
369 
373  static bool getPrintRCPNodeStatisticsOnExit();
374 
389  static void printActiveRCPNodes(std::ostream &out);
390 
392 
397 
402  static void addNewRCPNode(RCPNode* rcp_node,
403  const std::string &info );
404 
410  static void removeRCPNode( RCPNode* rcp_node );
411 
420  template<class T>
421  static const void* getRCPNodeBaseObjMapKeyVoidPtr(T *p)
422  {
423 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
424  return getBaseObjVoidPtr(p);
425 #else
426  // This will not return the base address for polymorphic types if
427  // multiple inheritance and/or virtual bases are used but returning the
428  // static_cast should be okay in how it is used. It is just that the
429  // RCPNode tracing support will not always be able to figure out if two
430  // pointers of different type are pointing to the same object or not.
431  return static_cast<const void*>(p);
432 #endif
433  }
434 
441  static RCPNode* getExistingRCPNodeGivenLookupKey(
442  const void* lookupKey);
443 
450  template<class T>
452  {
453  return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
454  }
455 
457  static std::string getActiveRCPNodeHeaderString();
458 
460  static std::string getCommonDebugNotesString();
461 
463 
464 };
465 
466 
467 #ifdef TEUCHOS_DEBUG
468 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \
469  " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n"
470 #else
471 # define TEUCHOS_RCP_INSERION_NUMBER_STR()
472 #endif
473 
474 
480 template<class T, class Dealloc_T>
481 class RCPNodeTmpl : public RCPNode {
482 public:
484  RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in)
485  : RCPNode(has_ownership_in), ptr_(p),
486 #ifdef TEUCHOS_DEBUG
487  base_obj_map_key_void_ptr_(RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
488  deleted_ptr_(0),
489 #endif
490  dealloc_(dealloc)
491  {}
493  RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in, ENull)
494  : RCPNode(has_ownership_in), ptr_(p),
495 #ifdef TEUCHOS_DEBUG
496  base_obj_map_key_void_ptr_(0),
497  deleted_ptr_(0),
498 #endif
499  dealloc_(dealloc)
500  {}
502  Dealloc_T& get_nonconst_dealloc()
503  { return dealloc_; }
505  const Dealloc_T& get_dealloc() const
506  { return dealloc_; }
509  {
510 #ifdef TEUCHOS_DEBUG
511  TEUCHOS_TEST_FOR_EXCEPTION( ptr_!=0, std::logic_error,
512  "Error, the underlying object must be explicitly deleted before deleting"
513  " the node object!" );
514 #endif
515  }
517  virtual bool is_valid_ptr() const
518  {
519  return ptr_ != 0;
520  }
526  virtual void delete_obj()
527  {
528  if (ptr_!= 0) {
529  this->pre_delete_extra_data(); // May throw!
530  T* tmp_ptr = ptr_;
531 #ifdef TEUCHOS_DEBUG
532  deleted_ptr_ = tmp_ptr;
533 #endif
534  ptr_ = 0;
535  if (has_ownership()) {
536 #ifdef TEUCHOS_DEBUG
537  try {
538 #endif
539  dealloc_.free(tmp_ptr);
540 #ifdef TEUCHOS_DEBUG
541  }
542  catch(...) {
543  // Object was not deleted due to an exception!
544  ptr_ = tmp_ptr;
545  throw;
546  }
547 #endif
548  }
549  // 2008/09/22: rabartl: Above, we have to be careful to set the member
550  // this->ptr_=0 before calling delete on the object's address in order
551  // to avoid a double call to delete in cases of circular references
552  // involving weak and strong pointers (see the unit test
553  // circularReference_c_then_a in RCP_UnitTests.cpp). NOTE: It is
554  // critcial that no member of *this get accesses after
555  // dealloc_.free(...) gets called! Also, in order to provide the
556  // "strong" guarantee we have to include the above try/catch. This
557  // overhead is unfortunate but I don't know of any other way to
558  // statisfy the "strong" guarantee and still avoid a double delete.
559  }
560  }
563  const std::string& rcp_type_name,
564  const void* rcp_ptr,
565  const RCPNode* rcp_node_ptr,
566  const void* rcp_obj_ptr
567  ) const
568  {
569  TEUCHOS_TEST_FOR_EXCEPT_MSG( ptr_!=0, "Internal coding error!" );
570  const T* deleted_ptr =
571 #ifdef TEUCHOS_DEBUG
572  deleted_ptr_
573 #else
574  0
575 #endif
576  ;
577  TEUCHOS_ASSERT(rcp_node_ptr);
579  "Error, an attempt has been made to dereference the underlying object\n"
580  "from a weak smart pointer object where the underling object has already\n"
581  "been deleted since the strong count has already gone to zero.\n"
582  "\n"
583  "Context information:\n"
584  "\n"
585  " RCP type: " << rcp_type_name << "\n"
586  " RCP address: " << rcp_ptr << "\n"
587  " RCPNode type: " << typeName(*this) << "\n"
588  " RCPNode address: " << rcp_node_ptr << "\n"
589  TEUCHOS_RCP_INSERION_NUMBER_STR()
590  " RCP ptr address: " << rcp_obj_ptr << "\n"
591  " Concrete ptr address: " << deleted_ptr << "\n"
592  "\n"
594  );
595  // 2008/09/22: rabartl: Above, we do not provide the concreate object
596  // type or the concrete object address. In the case of the concrete
597  // object address, in a non-debug build, we don't want to pay a price
598  // for extra storage that we strictly don't need. In the case of the
599  // concrete object type name, we don't want to force non-debug built
600  // code to have the require that types be fully defined in order to use
601  // the memory management software. This is related to bug 4016.
602 
603  }
605  const std::string get_base_obj_type_name() const
606  {
607 #ifdef TEUCHOS_DEBUG
608  return TypeNameTraits<T>::name();
609 #else
610  return "UnknownType";
611 #endif
612  }
613 #ifdef TEUCHOS_DEBUG
614 
615  const void* get_base_obj_map_key_void_ptr() const
616  {
617  return base_obj_map_key_void_ptr_;
618  }
619 #endif
620 private:
621  T *ptr_;
622 #ifdef TEUCHOS_DEBUG
623  const void *base_obj_map_key_void_ptr_;
624  T *deleted_ptr_;
625 #endif
626  Dealloc_T dealloc_;
627  // not defined and not to be called
628  RCPNodeTmpl();
629  RCPNodeTmpl(const RCPNodeTmpl&);
630  RCPNodeTmpl& operator=(const RCPNodeTmpl&);
631 
632 }; // end class RCPNodeTmpl<T>
633 
634 
642 class TEUCHOSCORE_LIB_DLL_EXPORT ActiveRCPNodesSetup {
643 public:
649  void foo();
650 private:
651  static int count_;
652 };
653 
654 
655 } // namespace Teuchos
656 
657 
658 namespace {
659 // This static variable is declared before all other static variables that
660 // depend on RCP or other classes. Therefore, this static variable will be
661 // deleted *after* all of these other static variables that depend on RCP or
662 // created classes go away! This ensures that the node tracing machinery is
663 // setup and torn down correctly (this is the same trick used by the standard
664 // stream objects in many compiler implementations).
665 Teuchos::ActiveRCPNodesSetup local_activeRCPNodesSetup;
666 } // namespace (anonymous)
667 
668 
669 namespace Teuchos {
670 
687 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeHandle {
688 public:
690  RCPNodeHandle (ENull null_arg = null)
691  : node_ (0), strength_ (RCP_STRONG)
692  {
693  (void) null_arg; // Silence "unused variable" compiler warning.
694  }
695 
698  ERCPStrength strength_in = RCP_STRONG,
699  bool newNode = true)
700  : node_ (node), strength_ (strength_in)
701  {
702 #ifdef TEUCHOS_DEBUG
703  TEUCHOS_ASSERT(node);
704 #endif // TEUCHOS_DEBUG
705 
706  bind();
707 
708 #ifdef TEUCHOS_DEBUG
709  // Add the node if this is the first RCPNodeHandle to get it. We have
710  // to add it because unbind() will call the remove_RCPNode(...) function
711  // and it needs to match when node tracing is on from the beginning.
712  if (RCPNodeTracer::isTracingActiveRCPNodes() && newNode) {
713  std::ostringstream os;
714  os << "{T=Unknown, ConcreteT=Unknown, p=Unknown,"
715  << " has_ownership="<<node_->has_ownership()<<"}";
716  RCPNodeTracer::addNewRCPNode(node_, os.str());
717  }
718 #else
719  (void) newNode; // Silence "unused variable" compiler warning.
720 #endif // TEUCHOS_DEBUG
721  }
722 
723 #ifdef TEUCHOS_DEBUG
724 
725  template<typename T>
726  RCPNodeHandle (RCPNode* node, T *p, const std::string &T_name,
727  const std::string &ConcreteT_name,
728  const bool has_ownership_in,
729  ERCPStrength strength_in = RCP_STRONG)
730  : node_ (node), strength_ (strength_in)
731  {
732  TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet!
733  TEUCHOS_ASSERT(node_);
734  bind();
736  std::ostringstream os;
737  os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name
738  <<", p="<<static_cast<const void*>(p)
739  <<", has_ownership="<<has_ownership_in<<"}";
740  RCPNodeTracer::addNewRCPNode(node_, os.str());
741  }
742  }
743 #endif // TEUCHOS_DEBUG
744 
746  RCPNodeHandle (const RCPNodeHandle& node_ref)
747  : node_ (node_ref.node_), strength_ (node_ref.strength_)
748  {
749  bind();
750  }
751 
753  void swap (RCPNodeHandle& node_ref) {
754  std::swap (node_ref.node_, node_);
755  std::swap (node_ref.strength_, strength_);
756  }
757 
763  RCPNodeHandle& operator= (const RCPNodeHandle& node_ref) {
764  // Assignment to self check: Note, We don't need to do an assigment to
765  // self check here because such a check is already done in the RCP and
766  // ArrayRCP classes.
767  // Take care of this's existing node and object
768  unbind(); // May throw in some cases
769  // Assign the new node
770  node_ = node_ref.node_;
771  strength_ = node_ref.strength_;
772  bind();
773  // Return
774  return *this;
775  }
776 
779  unbind();
780  }
781 
783  RCPNodeHandle create_weak() const {
784  if (node_) {
785  return RCPNodeHandle(node_, RCP_WEAK, false);
786  }
787  return RCPNodeHandle();
788  }
790  RCPNodeHandle create_strong() const {
791  if (node_) {
792  return RCPNodeHandle(node_, RCP_STRONG, false);
793  }
794  return RCPNodeHandle();
795  }
797  RCPNode* node_ptr() const {
798  return node_;
799  }
801  bool is_node_null() const {
802  return node_==0;
803  }
807  bool is_valid_ptr() const {
808  if (node_) {
809  return node_->is_valid_ptr();
810  }
811  return true; // Null is a valid ptr!
812  }
815  bool same_node(const RCPNodeHandle &node2) const {
816  return node_ == node2.node_;
817  }
819  int strong_count() const {
820  if (node_) {
821  return node_->strong_count();
822  }
823  return 0;
824  }
826  int weak_count() const {
827  if (node_) {
828  return node_->weak_count();
829  }
830  return 0;
831  }
833  int total_count() const {
834  if (node_) {
835  return node_->strong_count() + node_->weak_count();
836  }
837  return 0;
838  }
840  int count() const {
841  if (node_) {
842  return node_->strong_count();
843  }
844  return 0;
845  }
848  return strength_;
849  }
851  void has_ownership(bool has_ownership_in)
852  {
853  if (node_)
854  node_->has_ownership(has_ownership_in);
855  }
857  bool has_ownership() const
858  {
859  if (node_)
860  return node_->has_ownership();
861  return false;
862  }
865  const any &extra_data, const std::string& name,
866  EPrePostDestruction destroy_when, bool force_unique
867  )
868  {
869  debug_assert_not_null();
870  node_->set_extra_data(extra_data, name, destroy_when, force_unique);
871  }
873  any& get_extra_data( const std::string& type_name,
874  const std::string& name
875  )
876  {
877  debug_assert_not_null();
878  return node_->get_extra_data(type_name, name);
879  }
881  const any& get_extra_data( const std::string& type_name,
882  const std::string& name
883  ) const
884  {
885  return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name);
886  }
889  const std::string& type_name, const std::string& name
890  )
891  {
892  debug_assert_not_null();
893  return node_->get_optional_extra_data(type_name, name);
894  }
897  const std::string& type_name, const std::string& name
898  ) const
899  {
900  return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name);
901  }
904  {
905 #ifdef TEUCHOS_DEBUG
906  if (!node_)
907  throw_null_ptr_error(typeName(*this));
908 #endif
909  }
911  template<class RCPType>
912  void assert_valid_ptr(const RCPType& rcp_obj) const
913  {
914  if (!node_)
915  return; // Null is a valid pointer!
916  if (!is_valid_ptr()) {
917  node_->throw_invalid_obj_exception( typeName(rcp_obj),
918  this, node_, rcp_obj.access_private_ptr() );
919  }
920  }
922  template<class RCPType>
923  void debug_assert_valid_ptr(const RCPType& rcp_obj) const
924  {
925 #ifdef TEUCHOS_DEBUG
926  assert_valid_ptr(rcp_obj);
927 #endif
928  }
929 #ifdef TEUCHOS_DEBUG
930  const void* get_base_obj_map_key_void_ptr() const
931  {
932  if (node_)
933  return node_->get_base_obj_map_key_void_ptr();
934  return 0;
935  }
936 #endif
937 private:
938  RCPNode *node_;
939  ERCPStrength strength_;
940  inline void bind()
941  {
942  if (node_)
943  node_->incr_count(strength_);
944  }
945  inline void unbind()
946  {
947  // Optimize this implementation for count > 1
948  if (node_ && node_->deincr_count(strength_)==0) {
949  // If we get here, the reference count has gone to 0 and something
950  // interesting is going to happen. In this case, we need to
951  // reincrement the count back to 1 and call the more complex function
952  // that will either delete the object or delete the node.
953  node_->incr_count(strength_);
954  unbindOne();
955  }
956  // If we get here, either node_==0 or the count is still greater than 0.
957  // In this case, nothing interesting is going to happen so we are done!
958  }
959  void unbindOne(); // Provides the "strong" guarantee!
960 
961 };
962 
963 
968 inline
969 std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node)
970 {
971  // mfh 15 Sep 2015: Make sure that NULL pointers print consistently.
972  // Clang 3.5 likes to print an empty string in that case, while GCC
973  // prints 0. Thus, we test if the pointer is NULL and print 0 in
974  // that case. This is important for MueLu tests, which compare
975  // string print-outs.
976  if (node.node_ptr () == NULL) {
977  out << "0";
978  } else {
979  out << node.node_ptr ();
980  }
981  return out;
982 }
983 
984 
994 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeThrowDeleter {
995 public:
998  : node_(node)
999  {}
1006  {
1007  if (node_) {
1008  node_->has_ownership(false); // Avoid actually deleting ptr_
1009  node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete
1010  delete node_;
1011  }
1012  }
1014  RCPNode* get() const
1015  {
1016  return node_;
1017  }
1019  void release()
1020  {
1021  node_ = 0;
1022  }
1023 private:
1024  RCPNode *node_;
1025  RCPNodeThrowDeleter(); // Not defined
1026  RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined
1027  RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined
1028 };
1029 
1030 
1031 //
1032 // Unit testing support
1033 //
1034 
1035 
1036 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1037 
1038 class SetTracingActiveNodesStack {
1039 public:
1040  SetTracingActiveNodesStack()
1041  {RCPNodeTracer::setTracingActiveRCPNodes(true);}
1042  ~SetTracingActiveNodesStack()
1043  {RCPNodeTracer::setTracingActiveRCPNodes(false);}
1044 };
1045 
1046 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1047 
1048 #else
1049 
1050 # define SET_RCPNODE_TRACING() (void)0
1051 
1052 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1053 
1054 
1055 } // end namespace Teuchos
1056 
1057 
1058 #endif // TEUCHOS_RCP_NODE_HPP
Dangling reference error exception class.
const Dealloc_T & get_dealloc() const
bool has_ownership() const
int weak_count() const
The weak count for this RCPNode, or 0 if the node is NULL.
Modified boost::any class for holding a templated value.
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
virtual void throw_invalid_obj_exception(const std::string &rcp_type_name, const void *rcp_ptr, const RCPNode *rcp_node_ptr, const void *rcp_obj_ptr) const
static const void * getRCPNodeBaseObjMapKeyVoidPtr(T *p)
Get a const void* address to be used as the lookup key for an RCPNode given its embedded object&#39;s typ...
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Dealloc_T & get_nonconst_dealloc()
int deincr_count(const ERCPStrength strength)
any & get_extra_data(const std::string &type_name, const std::string &name)
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
RCPNodeHandle(ENull null_arg=null)
Default constructor.
void debug_assert_valid_ptr(const RCPType &rcp_obj) const
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
void release()
Releaes the RCPNode pointer before the destructor is called.
const std::string get_base_obj_type_name() const
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
Modified boost::any class, which is a container for a templated value.
Definition: Teuchos_any.hpp:86
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor.
RCPNodeHandle(RCPNode *node, ERCPStrength strength_in=RCP_STRONG, bool newNode=true)
Constructor that takes a pointer to an RCPNode.
Sets up node tracing and prints remaining RCPNodes on destruction.
void has_ownership(bool has_ownership_in)
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
Debug-mode RCPNode tracing class.
virtual void delete_obj()
Delete the underlying object.
Node class to keep track of address and the reference count for a reference-counted utility class and...
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in, ENull)
For undefined types .
Templated implementation class of RCPNode that has the responsibility for deleting the reference-coun...
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
void assert_valid_ptr(const RCPType &rcp_obj) const
void debugAssertStrength(ERCPStrength strength)
int incr_count(const ERCPStrength strength)
RCPNodeHandle create_strong() const
Return a strong handle.
ERCPStrength strength() const
The strength of this handle.
int strong_count() const
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
ERCPStrength
Used to specify if the pointer is weak or strong.
const any & get_extra_data(const std::string &type_name, const std::string &name) const
RCPNode(bool has_ownership_in)
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
void debug_assert_not_null() const
Provides std::map class for deficient platforms.
int weak_count() const
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
Handle class that manages the RCPNode&#39;s reference counting.
int strong_count() const
The strong count for this RCPNode, or 0 if the node is NULL.
void has_ownership(bool has_ownership_in)
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
int total_count() const
The sum of the weak and string counts.
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
bool is_valid_ptr() const
Whether the underlying pointer is valid.
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
bool same_node(const RCPNodeHandle &node2) const
Whether the RCPNode for which node2 is a handle is the same RCPNode as this object&#39;s RCPNode...
Deletes a (non-owning) RCPNode but not it&#39;s underlying object in case of a throw. ...
bool is_node_null() const
Whether the underlying RCPNode is NULL.
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
const any & get_extra_data(const std::string &type_name, const std::string &name) const
RCPNode * node_ptr() const
Return a pointer to the underlying RCPNode.
Default traits class for converting objects into strings.
RCPNodeHandle create_weak() const
Return a weak handle.
virtual bool is_valid_ptr() const
int count() const
The strong count; retained for backwards compatibility.
Defines basic traits returning the name of a type in a portable and readable way. ...
void swap(RCPNodeHandle &node_ref)
Swap the contents of node_ref with *this.
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.