IMP  2.0.0
The Integrative Modeling Platform
tracking.h
Go to the documentation of this file.
1 /**
2  * \file IMP/base/tracking.h \brief IO support.
3  *
4  * Copyright 2007-2013 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPBASE_TRACKING_H
9 #define IMPBASE_TRACKING_H
10 
11 #include <IMP/base/base_config.h>
12 #include "Object.h"
13 #include <IMP/base/set.h>
14 #include <IMP/base/Vector.h>
15 #include "WeakPointer.h"
16 #include <sstream>
17 IMPBASE_BEGIN_NAMESPACE
18 
19 /** By inheriting from this, an Object can keep track of a list
20  of objects as long as they are alive.
21 */
22 template <class Tracked>
23 class Tracker {
24  base::set<Tracked*> tracked_;
25  base::set<Tracked*> added_;
27  public:
28  Tracker(){}
29  Vector<Tracked*> get_tracked() {
30  return base::Vector<Tracked*>(tracked_.begin(),
31  tracked_.end());
32  };
33  void add_tracked(Tracked*tr) {
34  IMP_USAGE_CHECK(tr, "Can't track nullptr object");
35  IMP_CHECK_OBJECT(tr);
36  tracked_.insert(tr);
37  added_.insert(tr);
38  //can't remove it from removed as it might be a new one
39  // with the same address
40  }
41  void remove_tracked(Tracked*tr) {
42  IMP_USAGE_CHECK(tr, "Can't untrack nullptr");
43  IMP_CHECK_OBJECT(tr);
44  IMP_USAGE_CHECK(tracked_.find(tr) != tracked_.end(),
45  "Tracked object " << (tr ? tr->get_name():"nullptr")
46  << " not found.");
47  tracked_.erase(tr);
48  if (added_.find(tr) != added_.end()) {
49  added_.erase(tr);
50  } else {
51  removed_.insert(std::make_pair(tr, tr->get_name()));
52  }
53  }
54  bool get_is_dirty() const {return !added_.empty() || !removed_.empty();}
55  void set_is_dirty(bool tf) {
56  if (!tf) {
57  added_.clear();
58  removed_.clear();
59  }
60  }
61  std::string get_changed_description() const {
62  std::ostringstream oss;
63  if (!added_.empty()) {
64  oss << " Added: " << ObjectsTemp(added_.begin(), added_.end());
65  }
66  if (!removed_.empty()) {
67  oss << " Removed: [";
69  it= removed_.begin(); it != removed_.end(); ++it) {
70  oss << it->second << ", ";
71  }
72  oss << "]";
73  }
74  return oss.str();
75  }
76  typedef typename base::set<Tracked*>::const_iterator TrackedIterator;
77  TrackedIterator tracked_begin() const {
78  return tracked_.begin();
79  }
80  TrackedIterator tracked_end() const {
81  return tracked_.end();
82  }
83  ~Tracker() {
84  base::Vector<Tracked*> tracked(tracked_begin(), tracked_end());
85  for (unsigned int i=0; i< tracked_.size(); ++i) {
86  IMP_CHECK_OBJECT(tracked[i]);
87  tracked[i]->set_no_tracker();
88  }
89  }
90 };
91 
92 /** By inheriting from this, a record of the Object will be
93  maintained as long as it is alive.*/
94 template <class Type, class Tracker>
95 class TrackedObject: public Object {
99  public:
100  TrackedObject(Type *me, Tracker *tracker,
101  std::string name): Object(name) {
102  IMP_USAGE_CHECK(tracker, "Must pass non-null tracker in constructor.");
103  IMP_INTERNAL_CHECK(me, "The passed this pointer is null, bad.");
104  set_tracker(me, tracker);
105  }
106  TrackedObject(std::string name): Object(name) {}
107  void set_tracker(Type *me, Tracker *tracker) {
108  IMP_USAGE_CHECK(!tracker || me,
109  "Can't pass a null oject with a non-null tacker.");
110  if (tracker == tracker_) return;
111  if (tracker_) {
112  static_cast<T*>(tracker_.get())
113  ->remove_tracked(me_);
114  }
115  tracker_=tracker;
116  me_=me;
117  if (tracker_) {
118  static_cast<T*>(tracker_)->add_tracked(me_);
119  }
120  }
121  //! Used by the tracker when it is destroyed
122  void set_no_tracker() {
123  tracker_=nullptr;
124  me_=nullptr;
125  }
126  bool get_is_tracked() const {return tracker_;}
127  Tracker *get_tracker() const {return tracker_;}
128  ~TrackedObject() {
129  set_tracker(nullptr, nullptr);
130  }
131 };
132 
133 IMPBASE_END_NAMESPACE
134 
135 #endif /* IMPBASE_TRACKING_H */