ROSE  0.11.2.0
callbacks.h
1 #ifndef ROSE_Callbacks_H
2 #define ROSE_Callbacks_H
3 
4 #include <boost/thread/locks.hpp>
5 #include <boost/thread/mutex.hpp>
6 #include <list>
7 
8 namespace Rose {
9 
11 namespace Callbacks {
12 
14 enum Direction {
17 };
18 
81 template<class T>
82 class List {
83 public:
84  typedef T CallbackType;
85  typedef std::list<CallbackType*> CBList;
87 private:
88  mutable boost::mutex mutex_;
89  CBList list;
90 
91 public:
92  List() {}
93 
94  List(const List &other) {
95  boost::lock_guard<boost::mutex> lock(other.mutex_);
96  list = other.list;
97  }
98 
99  explicit List(CallbackType *callback) {
100  append(callback);
101  }
102 
106  size_t size() const {
107  boost::lock_guard<boost::mutex> lock(mutex_);
108  return list.size();
109  }
110 
116  bool empty() const {
117  boost::lock_guard<boost::mutex> lock(mutex_);
118  return list.empty();
119  }
120 
127  List& append(CallbackType *cb) {
128  assert(cb!=NULL);
129  boost::lock_guard<boost::mutex> lock(mutex_);
130  list.push_back(cb);
131  return *this;
132  }
133 
140  List& prepend(CallbackType *cb) {
141  assert(cb!=NULL);
142  boost::lock_guard<boost::mutex> lock(mutex_);
143  list.push_front(cb);
144  return *this;
145  }
146 
154  List& after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements = UNLIMITED) {
155  assert(cb!=NULL);
156  boost::lock_guard<boost::mutex> lock(mutex_);
157  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
158  if (*li==relative_to) {
159  li = list.insert(++li, cb);
160  --nreplacements;
161  }
162  }
163  return *this;
164  }
165 
171  List& before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements = UNLIMITED) {
172  assert(cb!=NULL);
173  boost::lock_guard<boost::mutex> lock(mutex_);
174  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
175  if (*li==relative_to) {
176  li = list.insert(li, cb);
177  ++li;
178  --nreplacements;
179  }
180  }
181  return *this;
182  }
183 
192  List& replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements = UNLIMITED, Direction dir = FORWARD) {
193  assert(new_cb!=NULL);
194  boost::lock_guard<boost::mutex> lock(mutex_);
195  if (FORWARD==dir) {
196  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
197  if (*li==old_cb) {
198  *li = new_cb;
199  --nreplacements;
200  }
201  }
202  } else {
203  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend() && nreplacements>0; ++li) {
204  if (*li==old_cb) {
205  *li = new_cb;
206  --nreplacements;
207  }
208  }
209  }
210  return *this;
211  }
212 
220  bool erase(CallbackType *cb, Direction dir=FORWARD) {
221  boost::lock_guard<boost::mutex> lock(mutex_);
222  if (FORWARD==dir) {
223  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
224  if (*li==cb) {
225  list.erase(li);
226  return true;
227  }
228  }
229  } else {
230  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
231  if (*li==cb) {
232  list.erase((++li).base());
233  return true;
234  }
235  }
236  }
237  return false;
238  }
239 
244  List& clear() {
245  boost::lock_guard<boost::mutex> lock(mutex_);
246  list.clear();
247  return *this;
248  }
249 
253  std::list<CallbackType*> callbacks() const {
254  boost::lock_guard<boost::mutex> lock(mutex_);
255  return list;
256  }
257 
270  template<class ArgumentType>
271  bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const {
272  CBList list = callbacks(); /* copy, so callbacks can safely modify this object's list */
273  if (FORWARD==dir) {
274  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
275  b = (**li)(b, args);
276  }
277  } else {
278  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
279  b = (**li)(b, args);
280  }
281  }
282  return b;
283  }
284 };
285 
286 } // namespace
287 } // namespace
288 
289 #endif /* ROSE_callbacks_H */
std::list< CallbackType * > callbacks() const
Returns a copy of the underlying STL vector of functors.
Definition: callbacks.h:253
List of callback functors.
Definition: callbacks.h:82
List & prepend(CallbackType *cb)
Prepend callback to beginning of list without copying it.
Definition: callbacks.h:140
const size_t UNLIMITED(-1)
Effictively unlimited size.
Traverse the list from back to front.
Definition: callbacks.h:16
List & replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements=UNLIMITED, Direction dir=FORWARD)
Replace one callback with another.
Definition: callbacks.h:192
Main namespace for the ROSE library.
std::list< CallbackType * > CBList
Standard vector of functor pointers.
Definition: callbacks.h:85
Direction
Direction of callback list traversal.
Definition: callbacks.h:14
List & before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=UNLIMITED)
Insert a callback before another.
Definition: callbacks.h:171
bool erase(CallbackType *cb, Direction dir=FORWARD)
Remove a callback from a list without destroying it.
Definition: callbacks.h:220
bool empty() const
Predicate to test whether the list is empty.
Definition: callbacks.h:116
Traverse the list from front to back.
Definition: callbacks.h:15
size_t size() const
Returns the number of callbacks in the list.
Definition: callbacks.h:106
List & append(CallbackType *cb)
Append a functor to the end of the list without copying it.
Definition: callbacks.h:127
List & clear()
Remove all callbacks from list without destroying them.
Definition: callbacks.h:244
T CallbackType
Functor class.
Definition: callbacks.h:84
List & after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=UNLIMITED)
Insert a callback after another.
Definition: callbacks.h:154
bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const
Invokes all functors in the callback list.
Definition: callbacks.h:271