IMP  2.0.0
The Integrative Modeling Platform
base/RefCounted.h
Go to the documentation of this file.
1 /**
2  * \file IMP/base/RefCounted.h
3  * \brief A common base class for ref counted objects.
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPBASE_REF_COUNTED_H
10 #define IMPBASE_REF_COUNTED_H
11 
12 #include <IMP/base/base_config.h>
13 #include "exception.h"
14 #include "utility_macros.h"
15 #include <boost/static_assert.hpp>
16 #include <boost/type_traits.hpp>
17 #include "NonCopyable.h"
18 
19 
20 #ifndef IMP_DOXYGEN
21 #ifndef SWIG
22 
23 namespace IMP {
24 namespace base {
25  class Object;
26  namespace internal {
27  template <class R, class E>
28  struct RefStuff;
29  }
30 }
31 }
32 #endif
33 #endif
34 
35 IMPBASE_BEGIN_NAMESPACE
36 
37 
38 //! Common base class for ref counted objects.
39 /** This base class implements reference counting when used in
40  conjunction with IMP::Pointer or IMP::WeakPointer objects.
41  Objects which inherit from IMP::RefCounted should be passed
42  using pointers and stored using IMP::Pointer and
43  IMP::WeakPointer objects. Users must be careful to avoid
44  cycles of reference counted pointers, otherwise memory will
45  never be reclaimed.
46 
47  \par Introduction to reference counting:
48  Reference counting is a technique for managing memory and
49  automatically freeing memory (destroying objects) when it
50  is no longer needed. In reference counting, each object has a reference
51  count, which tracks how many different places are using the
52  object. When this count goes to 0, the object is freed.\n\n
53  Python internally refence counts everything. C++, on the other hand,
54  requires extra steps be taken to ensure that objects
55  are reference counted properly.\n\n
56  In \imp, reference counting is done through the IMP::Pointer
57  and IMP::RefCounted classes. The former should be used instead of
58  a raw C++ pointer when storing a pointer to any object
59  inheriting from IMP::RefCounted.\n\n
60  Any time one is using reference counting, one needs to be aware
61  of cycles, since if, for example, object A contains an IMP::Pointer to
62  object B and object B contains an IMP::Pointer to object A,
63  their reference counts will never go to 0 even if both A
64  and B are no longer used. To avoid this, use an
65  IMP::WeakPointer in one of A or B.
66 
67  IMP::RefCounted provides no public methods or constructors.
68  It makes objects that inherit from it non-copyable.
69 
70  \see IMP_REF_COUNTED_DESTRUCTOR()
71  */
72 class IMPBASEEXPORT RefCounted: public NonCopyable
73 {
74 #ifndef IMP_DOXYGEN
75  static unsigned int live_objects_;
76 
77  void init() {
78 #if IMP_HAS_CHECKS >= IMP_INTERNAL
79  ++live_objects_;
80 #endif
81 #if IMP_HAS_CHECKS >= IMP_USAGE
82  check_value_=111111111;
83 #endif
84  count_=0;
85  }
86 
87 #ifndef _MSC_VER
88  template <class R, class E>
89  friend struct internal::RefStuff;
90 #else
91  public:
92 #endif // _MSC_VER
93  mutable int count_;
94 #if IMP_HAS_CHECKS >= IMP_USAGE
95  double check_value_;
96 #endif
97 protected:
98  RefCounted(){init();}
99  // things right.
100 #ifdef _MSC_VER
101 public:
102 #endif
103  // the virtual is not strictly needed but helps for getting
104  virtual ~RefCounted();
105 
106  public:
107 
108 #ifndef IMP_DOXYGEN
109  // Return whether the object already been freed
110  bool get_is_valid() const {
111 #if IMP_HAS_CHECKS == IMP_NONE
112  return true;
113 #else
114  return static_cast<int>(check_value_)==111111111;
115 #endif
116  }
117 
118  void show(std::ostream &)const {};
119 
120  std::string get_name() const {return "RefCounted";}
121 #endif
122 
123  unsigned int get_ref_count() const {
124  return count_;
125  }
126 
127  static unsigned int get_number_of_live_objects() {
128  // for debugging purposes only
129  return live_objects_;
130  }
131 #endif // IMP_DOXYGEN
132 
133  bool get_is_shared() const {
134  return count_ > 1;
135  }
136 
137 };
138 
139 IMPBASE_END_NAMESPACE
140 
141 #endif /* IMPBASE_REF_COUNTED_H */