Teuchos Package Browser (Single Doxygen Collection)  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"
61 
62 
63 namespace Teuchos {
64 
65 
71 
77 
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<>
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 
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:
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  {}
250  };
251  typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
252  int count_[2];
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 
303 public:
304 
307 
311  : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
312  totalNumRCPNodeDeletions(0)
313  {}
314  long int maxNumRCPNodes;
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 
378  static void setPrintActiveRcpNodesOnExit(bool printActiveRcpNodesOnExit);
379 
383  static bool getPrintActiveRcpNodesOnExit();
384 
400  static void printActiveRCPNodes(std::ostream &out);
401 
403 
408 
413  static void addNewRCPNode(RCPNode* rcp_node,
414  const std::string &info );
415 
421  static void removeRCPNode( RCPNode* rcp_node );
422 
431  template<class T>
432  static const void* getRCPNodeBaseObjMapKeyVoidPtr(T *p)
433  {
434 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
435  return getBaseObjVoidPtr(p);
436 #else
437  // This will not return the base address for polymorphic types if
438  // multiple inheritance and/or virtual bases are used but returning the
439  // static_cast should be okay in how it is used. It is just that the
440  // RCPNode tracing support will not always be able to figure out if two
441  // pointers of different type are pointing to the same object or not.
442  return static_cast<const void*>(p);
443 #endif
444  }
445 
452  static RCPNode* getExistingRCPNodeGivenLookupKey(
453  const void* lookupKey);
454 
461  template<class T>
463  {
464  return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
465  }
466 
468  static std::string getActiveRCPNodeHeaderString();
469 
471  static std::string getCommonDebugNotesString();
472 
474 
475 };
476 
477 
478 #ifdef TEUCHOS_DEBUG
479 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \
480  " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n"
481 #else
482 # define TEUCHOS_RCP_INSERION_NUMBER_STR()
483 #endif
484 
485 
491 template<class T, class Dealloc_T>
492 class RCPNodeTmpl : public RCPNode {
493 public:
495  RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in)
496  : RCPNode(has_ownership_in), ptr_(p),
497 #ifdef TEUCHOS_DEBUG
498  base_obj_map_key_void_ptr_(RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
499  deleted_ptr_(0),
500 #endif
501  dealloc_(dealloc)
502  {}
504  RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in, ENull)
505  : RCPNode(has_ownership_in), ptr_(p),
506 #ifdef TEUCHOS_DEBUG
507  base_obj_map_key_void_ptr_(0),
508  deleted_ptr_(0),
509 #endif
510  dealloc_(dealloc)
511  {}
513  Dealloc_T& get_nonconst_dealloc()
514  { return dealloc_; }
516  const Dealloc_T& get_dealloc() const
517  { return dealloc_; }
520  {
521 #ifdef TEUCHOS_DEBUG
522  TEUCHOS_TEST_FOR_EXCEPTION( ptr_!=0, std::logic_error,
523  "Error, the underlying object must be explicitly deleted before deleting"
524  " the node object!" );
525 #endif
526  }
528  virtual bool is_valid_ptr() const
529  {
530  return ptr_ != 0;
531  }
537  virtual void delete_obj()
538  {
539  if (ptr_!= 0) {
540  this->pre_delete_extra_data(); // May throw!
541  T* tmp_ptr = ptr_;
542 #ifdef TEUCHOS_DEBUG
543  deleted_ptr_ = tmp_ptr;
544 #endif
545  ptr_ = 0;
546  if (has_ownership()) {
547 #ifdef TEUCHOS_DEBUG
548  try {
549 #endif
550  dealloc_.free(tmp_ptr);
551 #ifdef TEUCHOS_DEBUG
552  }
553  catch(...) {
554  // Object was not deleted due to an exception!
555  ptr_ = tmp_ptr;
556  throw;
557  }
558 #endif
559  }
560  // 2008/09/22: rabartl: Above, we have to be careful to set the member
561  // this->ptr_=0 before calling delete on the object's address in order
562  // to avoid a double call to delete in cases of circular references
563  // involving weak and strong pointers (see the unit test
564  // circularReference_c_then_a in RCP_UnitTests.cpp). NOTE: It is
565  // critcial that no member of *this get accesses after
566  // dealloc_.free(...) gets called! Also, in order to provide the
567  // "strong" guarantee we have to include the above try/catch. This
568  // overhead is unfortunate but I don't know of any other way to
569  // statisfy the "strong" guarantee and still avoid a double delete.
570  }
571  }
574  const std::string& rcp_type_name,
575  const void* rcp_ptr,
576  const RCPNode* rcp_node_ptr,
577  const void* rcp_obj_ptr
578  ) const
579  {
580  TEUCHOS_TEST_FOR_EXCEPT_MSG( ptr_!=0, "Internal coding error!" );
581  const T* deleted_ptr =
582 #ifdef TEUCHOS_DEBUG
583  deleted_ptr_
584 #else
585  0
586 #endif
587  ;
588  TEUCHOS_ASSERT(rcp_node_ptr);
590  "Error, an attempt has been made to dereference the underlying object\n"
591  "from a weak smart pointer object where the underling object has already\n"
592  "been deleted since the strong count has already gone to zero.\n"
593  "\n"
594  "Context information:\n"
595  "\n"
596  " RCP type: " << rcp_type_name << "\n"
597  " RCP address: " << rcp_ptr << "\n"
598  " RCPNode type: " << typeName(*this) << "\n"
599  " RCPNode address: " << rcp_node_ptr << "\n"
601  " RCP ptr address: " << rcp_obj_ptr << "\n"
602  " Concrete ptr address: " << deleted_ptr << "\n"
603  "\n"
605  );
606  // 2008/09/22: rabartl: Above, we do not provide the concreate object
607  // type or the concrete object address. In the case of the concrete
608  // object address, in a non-debug build, we don't want to pay a price
609  // for extra storage that we strictly don't need. In the case of the
610  // concrete object type name, we don't want to force non-debug built
611  // code to have the require that types be fully defined in order to use
612  // the memory management software. This is related to bug 4016.
613 
614  }
616  const std::string get_base_obj_type_name() const
617  {
618 #ifdef TEUCHOS_DEBUG
619  return TypeNameTraits<T>::name();
620 #else
621  return "UnknownType";
622 #endif
623  }
624 #ifdef TEUCHOS_DEBUG
625 
626  const void* get_base_obj_map_key_void_ptr() const
627  {
628  return base_obj_map_key_void_ptr_;
629  }
630 #endif
631 private:
632  T *ptr_;
633 #ifdef TEUCHOS_DEBUG
634  const void *base_obj_map_key_void_ptr_;
635  T *deleted_ptr_;
636 #endif
637  Dealloc_T dealloc_;
638  // not defined and not to be called
639  RCPNodeTmpl();
640  RCPNodeTmpl(const RCPNodeTmpl&);
642 
643 }; // end class RCPNodeTmpl<T>
644 
645 
654 public:
660  void foo();
661 private:
662  static int count_;
663 };
664 
665 
666 } // namespace Teuchos
667 
668 
669 namespace {
670 // This static variable is declared before all other static variables that
671 // depend on RCP or other classes. Therefore, this static variable will be
672 // deleted *after* all of these other static variables that depend on RCP or
673 // created classes go away! This ensures that the node tracing machinery is
674 // setup and torn down correctly (this is the same trick used by the standard
675 // stream objects in many compiler implementations).
676 Teuchos::ActiveRCPNodesSetup local_activeRCPNodesSetup;
677 } // namespace (anonymous)
678 
679 
680 namespace Teuchos {
681 
699 public:
701  RCPNodeHandle (ENull null_arg = null)
702  : node_ (0), strength_ (RCP_STRONG)
703  {
704  (void) null_arg; // Silence "unused variable" compiler warning.
705  }
706 
709  ERCPStrength strength_in = RCP_STRONG,
710  bool newNode = true)
711  : node_ (node), strength_ (strength_in)
712  {
713 #ifdef TEUCHOS_DEBUG
714  TEUCHOS_ASSERT(node);
715 #endif // TEUCHOS_DEBUG
716 
717  bind();
718 
719 #ifdef TEUCHOS_DEBUG
720  // Add the node if this is the first RCPNodeHandle to get it. We have
721  // to add it because unbind() will call the remove_RCPNode(...) function
722  // and it needs to match when node tracing is on from the beginning.
723  if (RCPNodeTracer::isTracingActiveRCPNodes() && newNode) {
724  std::ostringstream os;
725  os << "{T=Unknown, ConcreteT=Unknown, p=Unknown,"
726  << " has_ownership="<<node_->has_ownership()<<"}";
727  RCPNodeTracer::addNewRCPNode(node_, os.str());
728  }
729 #else
730  (void) newNode; // Silence "unused variable" compiler warning.
731 #endif // TEUCHOS_DEBUG
732  }
733 
734 #ifdef TEUCHOS_DEBUG
735 
736  template<typename T>
737  RCPNodeHandle (RCPNode* node, T *p, const std::string &T_name,
738  const std::string &ConcreteT_name,
739  const bool has_ownership_in,
740  ERCPStrength strength_in = RCP_STRONG)
741  : node_ (node), strength_ (strength_in)
742  {
743  TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet!
744  TEUCHOS_ASSERT(node_);
745  bind();
747  std::ostringstream os;
748  os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name
749  <<", p="<<static_cast<const void*>(p)
750  <<", has_ownership="<<has_ownership_in<<"}";
751  RCPNodeTracer::addNewRCPNode(node_, os.str());
752  }
753  }
754 #endif // TEUCHOS_DEBUG
755 
757  RCPNodeHandle (const RCPNodeHandle& node_ref)
758  : node_ (node_ref.node_), strength_ (node_ref.strength_)
759  {
760  bind();
761  }
762 
764  void swap (RCPNodeHandle& node_ref) {
765  std::swap (node_ref.node_, node_);
766  std::swap (node_ref.strength_, strength_);
767  }
768 
774  RCPNodeHandle& operator= (const RCPNodeHandle& node_ref) {
775  // Assignment to self check: Note, We don't need to do an assigment to
776  // self check here because such a check is already done in the RCP and
777  // ArrayRCP classes.
778  // Take care of this's existing node and object
779  unbind(); // May throw in some cases
780  // Assign the new node
781  node_ = node_ref.node_;
782  strength_ = node_ref.strength_;
783  bind();
784  // Return
785  return *this;
786  }
787 
790  unbind();
791  }
792 
795  if (node_) {
796  return RCPNodeHandle(node_, RCP_WEAK, false);
797  }
798  return RCPNodeHandle();
799  }
802  if (node_) {
803  return RCPNodeHandle(node_, RCP_STRONG, false);
804  }
805  return RCPNodeHandle();
806  }
808  RCPNode* node_ptr() const {
809  return node_;
810  }
812  bool is_node_null() const {
813  return node_==0;
814  }
818  bool is_valid_ptr() const {
819  if (node_) {
820  return node_->is_valid_ptr();
821  }
822  return true; // Null is a valid ptr!
823  }
826  bool same_node(const RCPNodeHandle &node2) const {
827  return node_ == node2.node_;
828  }
830  int strong_count() const {
831  if (node_) {
832  return node_->strong_count();
833  }
834  return 0;
835  }
837  int weak_count() const {
838  if (node_) {
839  return node_->weak_count();
840  }
841  return 0;
842  }
844  int total_count() const {
845  if (node_) {
846  return node_->strong_count() + node_->weak_count();
847  }
848  return 0;
849  }
851  int count() const {
852  if (node_) {
853  return node_->strong_count();
854  }
855  return 0;
856  }
859  return strength_;
860  }
862  void has_ownership(bool has_ownership_in)
863  {
864  if (node_)
865  node_->has_ownership(has_ownership_in);
866  }
868  bool has_ownership() const
869  {
870  if (node_)
871  return node_->has_ownership();
872  return false;
873  }
876  const any &extra_data, const std::string& name,
877  EPrePostDestruction destroy_when, bool force_unique
878  )
879  {
880  debug_assert_not_null();
881  node_->set_extra_data(extra_data, name, destroy_when, force_unique);
882  }
884  any& get_extra_data( const std::string& type_name,
885  const std::string& name
886  )
887  {
888  debug_assert_not_null();
889  return node_->get_extra_data(type_name, name);
890  }
892  const any& get_extra_data( const std::string& type_name,
893  const std::string& name
894  ) const
895  {
896  return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name);
897  }
900  const std::string& type_name, const std::string& name
901  )
902  {
903  debug_assert_not_null();
904  return node_->get_optional_extra_data(type_name, name);
905  }
908  const std::string& type_name, const std::string& name
909  ) const
910  {
911  return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name);
912  }
915  {
916 #ifdef TEUCHOS_DEBUG
917  if (!node_)
918  throw_null_ptr_error(typeName(*this));
919 #endif
920  }
922  template<class RCPType>
923  void assert_valid_ptr(const RCPType& rcp_obj) const
924  {
925  if (!node_)
926  return; // Null is a valid pointer!
927  if (!is_valid_ptr()) {
928  node_->throw_invalid_obj_exception( typeName(rcp_obj),
929  this, node_, rcp_obj.access_private_ptr() );
930  }
931  }
933  template<class RCPType>
934  void debug_assert_valid_ptr(const RCPType& rcp_obj) const
935  {
936 #ifdef TEUCHOS_DEBUG
937  assert_valid_ptr(rcp_obj);
938 #endif
939  }
940 #ifdef TEUCHOS_DEBUG
941  const void* get_base_obj_map_key_void_ptr() const
942  {
943  if (node_)
944  return node_->get_base_obj_map_key_void_ptr();
945  return 0;
946  }
947 #endif
948 private:
951  inline void bind()
952  {
953  if (node_)
954  node_->incr_count(strength_);
955  }
956  inline void unbind()
957  {
958  // Optimize this implementation for count > 1
959  if (node_ && node_->deincr_count(strength_)==0) {
960  // If we get here, the reference count has gone to 0 and something
961  // interesting is going to happen. In this case, we need to
962  // reincrement the count back to 1 and call the more complex function
963  // that will either delete the object or delete the node.
964  node_->incr_count(strength_);
965  unbindOne();
966  }
967  // If we get here, either node_==0 or the count is still greater than 0.
968  // In this case, nothing interesting is going to happen so we are done!
969  }
970  void unbindOne(); // Provides the "strong" guarantee!
971 
972 };
973 
974 
979 inline
980 std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node)
981 {
982  // mfh 15 Sep 2015: Make sure that NULL pointers print consistently.
983  // Clang 3.5 likes to print an empty string in that case, while GCC
984  // prints 0. Thus, we test if the pointer is NULL and print 0 in
985  // that case. This is important for MueLu tests, which compare
986  // string print-outs.
987  if (node.node_ptr () == NULL) {
988  out << "0";
989  } else {
990  out << node.node_ptr ();
991  }
992  return out;
993 }
994 
995 
1006 public:
1009  : node_(node)
1010  {}
1017  {
1018  if (node_) {
1019  node_->has_ownership(false); // Avoid actually deleting ptr_
1020  node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete
1021  delete node_;
1022  }
1023  }
1025  RCPNode* get() const
1026  {
1027  return node_;
1028  }
1030  void release()
1031  {
1032  node_ = 0;
1033  }
1034 private:
1036  RCPNodeThrowDeleter(); // Not defined
1037  RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined
1038  RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined
1039 };
1040 
1041 
1042 //
1043 // Unit testing support
1044 //
1045 
1046 
1047 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1048 
1049 class SetTracingActiveNodesStack {
1050 public:
1051  SetTracingActiveNodesStack()
1052  {RCPNodeTracer::setTracingActiveRCPNodes(true);}
1053  ~SetTracingActiveNodesStack()
1054  {RCPNodeTracer::setTracingActiveRCPNodes(false);}
1055 };
1056 
1057 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1058 
1059 #else
1060 
1061 # define SET_RCPNODE_TRACING() (void)0
1062 
1063 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1064 
1065 
1066 } // end namespace Teuchos
1067 
1068 
1069 #endif // TEUCHOS_RCP_NODE_HPP
Dangling reference error exception class.
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.
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
Modified boost::any class for holding a templated value.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
void assert_valid_ptr(const RCPType &rcp_obj) 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.
static std::string toString(const ERCPStrength &t)
#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)
const any & get_extra_data(const std::string &type_name, const std::string &name) const
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.
int count() const
The strong count; retained for backwards compatibility.
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
void release()
Releaes the RCPNode pointer before the destructor is called.
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
void debug_assert_not_null() const
Modified boost::any class, which is a container for a templated value.
Definition: Teuchos_any.hpp:86
RCPNodeTmpl & operator=(const RCPNodeTmpl &)
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor.
RCPNodeHandle create_strong() const
Return a strong handle.
extra_data_entry_t()
int weak_count() const
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.
void debug_assert_valid_ptr(const RCPType &rcp_obj) const
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 .
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...
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...
#define TEUCHOSCORE_LIB_DLL_EXPORT
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.
void debugAssertStrength(ERCPStrength strength)
int incr_count(const ERCPStrength strength)
bool is_node_null() const
Whether the underlying RCPNode is NULL.
RCPNode(bool has_ownership_in)
#define TEUCHOS_RCP_INSERION_NUMBER_STR()
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
int weak_count() const
The weak count for this RCPNode, or 0 if the node is NULL.
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
Provides std::map class for deficient platforms.
int strong_count() const
virtual bool is_valid_ptr() const
ERCPStrength strength() const
The strength of this handle.
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
bool is_valid_ptr() const
Whether the underlying pointer is valid.
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.
const std::string get_base_obj_type_name() const
void has_ownership(bool has_ownership_in)
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
extra_data_map_t * extra_data_map_
RCPNodeHandle create_weak() const
Return a weak handle.
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
bool has_ownership() const
extra_data_entry_t(const any &_extra_data, EPrePostDestruction _destroy_when)
Deletes a (non-owning) RCPNode but not it&#39;s underlying object in case of a throw. ...
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
Default traits class for converting objects into strings.
Teuchos::map< std::string, extra_data_entry_t > extra_data_map_t
EPrePostDestruction destroy_when
any extra_data
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.
int total_count() const
The sum of the weak and string counts.
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...
const Dealloc_T & get_dealloc() const