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