ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
callbacks.h
Go to the documentation of this file.
1 #ifndef ROSE_Callbacks_H
2 #define ROSE_Callbacks_H
3 
4 #include "threadSupport.h"
5 #include <list>
6 
8 namespace ROSE_Callbacks {
9 
11  enum Direction {
14  };
15 
78  template<class T>
79  class List {
80  public:
81  typedef T CallbackType;
82  typedef std::list<CallbackType*> CBList;
84  List() {
86  }
87 
88  explicit List(CallbackType *callback) {
90  append(callback);
91  }
92 
96  size_t size() const {
97  size_t retval = 0;
98  RTS_MUTEX(mutex) {
99  retval = list.size();
100  } RTS_MUTEX_END;
101  return retval;
102  }
103 
107  bool empty() const {
108  bool retval = false;
109  RTS_MUTEX(mutex) {
110  retval = list.empty();
111  } RTS_MUTEX_END;
112  return retval;
113  }
114 
121  RTS_MUTEX(mutex) {
122  assert(cb!=NULL);
123  list.push_back(cb);
124  } RTS_MUTEX_END;
125  return *this;
126  }
127 
134  RTS_MUTEX(mutex) {
135  assert(cb!=NULL);
136  list.push_front(cb);
137  } RTS_MUTEX_END;
138  return *this;
139  }
140 
146  List& after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
147  RTS_MUTEX(mutex) {
148  assert(cb!=NULL);
149  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
150  if (*li==relative_to) {
151  li = list.insert(++li, cb);
152  --nreplacements;
153  }
154  }
155  } RTS_MUTEX_END;
156  return *this;
157  }
158 
164  List& before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
165  RTS_MUTEX(mutex) {
166  assert(cb!=NULL);
167  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
168  if (*li==relative_to) {
169  li = list.insert(li, cb);
170  ++li;
171  --nreplacements;
172  }
173  }
174  } RTS_MUTEX_END;
175  return *this;
176  }
177 
184  List& replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements=(size_t)(-1), Direction dir=FORWARD) {
185  RTS_MUTEX(mutex) {
186  assert(new_cb!=NULL);
187  if (FORWARD==dir) {
188  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
189  if (*li==old_cb) {
190  *li = new_cb;
191  --nreplacements;
192  }
193  }
194  } else {
195  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend() && nreplacements>0; ++li) {
196  if (*li==old_cb) {
197  *li = new_cb;
198  --nreplacements;
199  }
200  }
201  }
202  } RTS_MUTEX_END;
203  return *this;
204  }
205 
213  bool erased = false;
214  RTS_MUTEX(mutex) {
215  if (FORWARD==dir) {
216  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
217  if (*li==cb) {
218  list.erase(li);
219  erased = true;
220  break;
221  }
222  }
223  } else {
224  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
225  if (*li==cb) {
226  list.erase((++li).base());
227  erased = true;
228  break;
229  }
230  }
231  }
232  } RTS_MUTEX_END;
233  return erased;
234  }
235 
240  List& clear() {
241  RTS_MUTEX(mutex) {
242  list.clear();
243  } RTS_MUTEX_END;
244  return *this;
245  }
246 
250  std::list<CallbackType*> callbacks() const {
251  CBList retval;
252  RTS_MUTEX(mutex) {
253  retval = list;
254  } RTS_MUTEX_END;
255  return retval;
256  }
257 
268  template<class ArgumentType>
269  bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const {
270  CBList list = callbacks(); /* copy, so callbacks can safely modify this object's list */
271  if (FORWARD==dir) {
272  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
273  b = (**li)(b, args);
274  }
275  } else {
276  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
277  b = (**li)(b, args);
278  }
279  }
280  return b;
281  }
282 
283  private:
286  };
287 }
288 
289 #endif /* ROSE_callbacks_H */