IMP  2.1.0
The Integrative Modeling Platform
base/declare_Object.h
Go to the documentation of this file.
1 /**
2  * \file IMP/base/declare_Object.h
3  * \brief A shared base class to help in debugging and things.
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPBASE_DECLARE_OBJECT_H
10 #define IMPBASE_DECLARE_OBJECT_H
11 
12 #include <IMP/base/base_config.h>
13 #include <IMP/base/base_config.h>
14 #include "exception.h"
15 #include "utility_macros.h"
16 #include <boost/static_assert.hpp>
17 #include <boost/type_traits.hpp>
18 #include "NonCopyable.h"
19 #include "ref_counted_macros.h"
20 #include "enums.h"
21 #include "hash_macros.h"
22 #include "warning_macros.h"
23 #include "showable_macros.h"
24 #include "VersionInfo.h"
25 #include "utility_macros.h"
26 #include <IMP/base/hash.h>
27 #include "hash.h"
28 #include <boost/scoped_array.hpp>
29 
30 #if !defined(IMP_HAS_CHECKS)
31 #error "IMP_HAS_CHECKS not defined, something is broken"
32 #endif
33 #if !defined(IMP_NONE)
34 #error "IMP_NONE not defined, something is broken"
35 #endif
36 #if !defined(IMP_HAS_LOG)
37 #error "IMP_HAS_LOG not defined, something is broken"
38 #endif
39 #if !defined(IMP_SILENT)
40 #error "IMP_SILENT not defined, something is broken"
41 #endif
42 
43 #ifndef IMP_DOXYGEN
44 #ifndef SWIG
45 
46 namespace IMP {
47 namespace base {
48 class Object;
49 namespace internal {
50 template <class R, class E>
51 struct RefStuff;
52 }
53 }
54 }
55 #endif
56 #endif
57 
58 IMPBASE_BEGIN_NAMESPACE
59 
60 //! Common base class for heavy weight \imp objects.
61 /**
62 The base class for non \ref introduction_values "value-type classes" in
63 \imp. Anything inheriting from Object has the following properties:
64 
65 - has embedded information about the module and version which can
66 be accessed using Object::get_version_info(). This information can
67 be used to log what version of software is used to compute a
68 result.
69 
70 - it has a local logging level which can override the global one
71 allowing fine grained logging control.
72 
73 - in python, there is a method Class::get_from(Object *o) that
74 attempts to case o to an object of type Class and throws and
75 exception if it fails.
76 
77 - the object keeps track of whether it has been been used. See the
78 Object::set_was_used() method for an explanation.
79 
80 - It is reference counted
81 
82 Types inheriting from Object should always be created using \c new
83 in C++ and passed using pointers and stored using Pointer
84 objects. Note that you have to be careful of cycles and so must
85 use WeakPointer objects to break cycles. IMP_NEW() can help shorten
86 creating a ref counted pointer. See Pointer for more
87 information.
88 
89 See example::ExampleObject for a simple example.
90 
91 Reference counting is a technique for managing memory and
92 automatically freeing memory (destroying objects) when it is no
93 longer needed. In reference counting, each object has a reference
94 count, which tracks how many different places are using the
95 object. When this count goes to 0, the object is freed.
96 
97 Python internally refence counts everything. C++, on the other
98 hand, requires extra steps be taken to ensure that objects are
99 reference counted properly.
100 
101 In \imp, reference counting is done through the Pointer,
102 PointerMember and Object classes. The former should be used
103 instead of a raw C++ pointer when storing a pointer to any object
104 inheriting from Object.
105 
106 Any time one is using reference
107 counting, one needs to be aware of cycles, since if, for example,
108 object A contains an IMP::Pointer to object B and object B
109 contains an Pointer to object A, their reference counts will never
110 go to 0 even if both A and B are no longer used. To avoid this,
111 use an WeakPointer in one of A or B.
112 
113 Functions that create new objects should follow the following pattern
114 
115  ObjectType *create_object(arguments) {
116  IMP_NEW(ObjectType, ret, (args));
117  do_stuff;
118  return ret.release();
119  }
120 
121 using Pointer::release() to safely return the new object without freeing it.
122 */
123 class IMPBASEEXPORT Object : public NonCopyable {
124  std::string name_;
125  boost::scoped_array<char> quoted_name_;
126 
127  static unsigned int live_objects_;
128 #ifdef _MSC_VER
129  public:
130 #endif
131  mutable int count_;
132 #ifdef _MSC_VER
133  private:
134 #endif
135 
136 #if IMP_HAS_LOG != IMP_NONE
137  LogLevel log_level_;
138 #endif
139 
140 #if IMP_HAS_CHECKS >= IMP_USAGE
141  CheckLevel check_level_;
142  mutable bool was_owned_;
143  double check_value_;
144 #endif
145 
146 #if IMP_HAS_CHECKS >= IMP_INTERNAL
147  static void add_live_object(Object* o);
148  static void remove_live_object(Object* o);
149 #endif
150 
151  void initialize(std::string name);
152 
153  int compare(const Object& o) const {
154  if (&o < this)
155  return 1;
156  else if (&o > this)
157  return -1;
158  else
159  return 0;
160  }
162 
163  protected:
164  //! Construct an object with the given name
165  /** An instance of "%1%" in the string will be replaced by a unique
166  index.
167  */
168  Object(std::string name);
169 
170  /** \deprecated_at{2.1} Provide a name. */
171  IMPBASE_DEPRECATED_FUNCTION_DECL(2.1)
172  Object();
173 
174  public:
175  // needed for python to make sure all wrapper objects are equivalent
176  IMP_HASHABLE_INLINE(Object, return boost::hash_value(this););
177 
178  //! Set the logging level used in this object
179  /** Each object can be assigned a different log level in order to,
180  for example, suppress messages for verbose and uninteresting
181  objects. If set to DEFAULT, the global level as returned by
182  IMP::get_log_level() is used, otherwise
183  the local one is used. Methods in classes inheriting from
184  Object should start with IMP_OBJECT_LOG to change the log
185  level to the local one for this object and increase
186  the current indent.
187 
188  \see IMP::base::set_log_level()
189  \see IMP::base::get_log_level()
190  */
191  void set_log_level(LogLevel l);
192 
193  /** Each object can be assigned a different check level too.
194  */
195  void set_check_level(CheckLevel l);
196  LogLevel get_log_level() const;
197  CheckLevel get_check_level() const;
198 
199  //! Get information about the module and version of the object
200  virtual VersionInfo get_version_info() const {
201  return VersionInfo("none", "none");
202  }
203 
204  /** @name Names
205  All objects have names to aid in debugging and inspection
206  of the state of the system. These names are not necessarily unique
207  and should not be used to store data or as keys into a table. Use
208  the address of the object instead since objects cannot be copied.
209  @{
210  */
211  const std::string& get_name() const { return name_; }
212  void set_name(std::string name);
213  virtual std::string get_type_name() const { return "unknown object type"; }
214  /* @} */
215 
216  /** \imp provides warnings when objects are never used before they are
217  destroyed. Examples of use include adding an IMP::Restraint to an
218  IMP::kernel::Model. If an object is not properly marked as used, or your
219  code is the one using it, call set_was_used(true) on the object.
220  */
221  void set_was_used(bool tf) const;
222 
223  IMP_SHOWABLE(Object);
224 
225 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
226  const char* get_quoted_name_c_string() const { return quoted_name_.get(); }
227 #endif
228 
229 #ifndef IMP_DOXYGEN
230  void _debugger_show() const { show(std::cout); }
231 
232  //! Return a string version of the object, can be used in the debugger
233  std::string get_string() const {
234  std::ostringstream oss;
235  show(oss);
236  return oss.str();
237  }
238 
239  void _on_destruction();
240 
241  //! Return whether the object already been freed
242  bool get_is_valid() const;
243 
244  unsigned int get_ref_count() const { return count_; }
245 
246  static unsigned int get_number_of_live_objects() { return live_objects_; }
247  bool get_is_shared() const { return count_ > 1; }
248 #endif // IMP_DOXYGEN
249 
250  /** Objects can have internal caches. This method resets them returning
251  the object to its just-initialized state.
252  */
253  virtual void clear_caches() {}
254 
255  /** Overide this method to take action on destruction. */
256  virtual void do_destroy() {}
257 };
258 
259 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
260 inline void Object::set_check_level(CheckLevel l) {
261  IMP_CHECK_VARIABLE(l);
262 #if IMP_HAS_CHECKS != IMP_NONE
263  check_level_ = l;
264 #endif
265 }
266 
267 inline LogLevel Object::get_log_level() const {
268 #if IMP_HAS_LOG == IMP_SILENT
269  return SILENT;
270 #else
271  return log_level_;
272 #endif
273 }
274 inline CheckLevel Object::get_check_level() const {
275 #if IMP_HAS_CHECKS == IMP_NONE
276  return NONE;
277 #else
278  return check_level_;
279 #endif
280 }
281 
282 inline void Object::set_was_used(bool tf) const {
283  IMP_CHECK_VARIABLE(tf);
284 #if IMP_HAS_CHECKS >= IMP_USAGE
285  was_owned_ = tf;
286 #endif
287 }
288 
289 inline bool Object::get_is_valid() const {
290 #if IMP_HAS_CHECKS == IMP_NONE
291  return true;
292 #else
293  return static_cast<int>(check_value_) == 111111111;
294 #endif
295 }
296 #endif
297 
298 IMPBASE_END_NAMESPACE
299 
300 #endif /* IMPBASE_DECLARE_OBJECT_H */
CheckLevel
Specify the level of runtime checks performed.
Definition: base/enums.h:52
LogLevel
The log levels supported by IMP.
Definition: base/enums.h:18
void set_log_level(LogLevel l)
Set the current global log level.
void set_check_level(CheckLevel tf)
Control runtime checks in the code.
Various general useful macros for IMP.
#define IMP_HASHABLE_INLINE(name, hashret)
LogLevel get_log_level()
Get the currently active global log level.
Definition: base/log.h:93
virtual void clear_caches()
virtual VersionInfo get_version_info() const
Get information about the module and version of the object.
#define IMP_SHOWABLE(Name)
int compare(const VectorD< D > &a, const VectorD< D > &b)
lexicographic comparison of two vectors
Definition: VectorD.h:371
Version and authorship of IMP objects.
Various general useful macros for IMP.
Various general useful macros for IMP.
Basic types used by IMP.
#define IMP_REF_COUNTED_NONTRIVIAL_DESTRUCTOR(Name)
Various general useful macros for IMP.
IO support.
Common base class for heavy weight IMP objects.
Exception definitions and assertions.
Version and module information for Objects.
void show(Hierarchy h, std::ostream &out=std::cout)
Print out a molecular hierarchy.
virtual void do_destroy()
Various general useful macros for IMP.
CheckLevel get_check_level()
Get the current audit mode.
Basic types used by IMP.