ROSE  0.9.9.139
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 
9 namespace ROSE_Callbacks {
10 
12  enum Direction {
15  };
16 
79  template<class T>
80  class List {
81  public:
82  typedef T CallbackType;
83  typedef std::list<CallbackType*> CBList;
85  private:
86  mutable boost::mutex mutex_;
87  CBList list;
88 
89  public:
90  List() {}
91 
92  List(const List &other) {
93  boost::lock_guard<boost::mutex> lock(other.mutex_);
94  list = other.list;
95  }
96 
97  explicit List(CallbackType *callback) {
98  append(callback);
99  }
100 
104  size_t size() const {
105  boost::lock_guard<boost::mutex> lock(mutex_);
106  return list.size();
107  }
108 
112  bool empty() const {
113  boost::lock_guard<boost::mutex> lock(mutex_);
114  return list.empty();
115  }
116 
122  List& append(CallbackType *cb) {
123  assert(cb!=NULL);
124  boost::lock_guard<boost::mutex> lock(mutex_);
125  list.push_back(cb);
126  return *this;
127  }
128 
134  List& prepend(CallbackType *cb) {
135  assert(cb!=NULL);
136  boost::lock_guard<boost::mutex> lock(mutex_);
137  list.push_front(cb);
138  return *this;
139  }
140 
146  List& after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
147  assert(cb!=NULL);
148  boost::lock_guard<boost::mutex> lock(mutex_);
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  return *this;
156  }
157 
163  List& before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
164  assert(cb!=NULL);
165  boost::lock_guard<boost::mutex> lock(mutex_);
166  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
167  if (*li==relative_to) {
168  li = list.insert(li, cb);
169  ++li;
170  --nreplacements;
171  }
172  }
173  return *this;
174  }
175 
182  List& replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements=(size_t)(-1), Direction dir=FORWARD) {
183  assert(new_cb!=NULL);
184  boost::lock_guard<boost::mutex> lock(mutex_);
185  if (FORWARD==dir) {
186  for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
187  if (*li==old_cb) {
188  *li = new_cb;
189  --nreplacements;
190  }
191  }
192  } else {
193  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend() && nreplacements>0; ++li) {
194  if (*li==old_cb) {
195  *li = new_cb;
196  --nreplacements;
197  }
198  }
199  }
200  return *this;
201  }
202 
209  bool erase(CallbackType *cb, Direction dir=FORWARD) {
210  boost::lock_guard<boost::mutex> lock(mutex_);
211  if (FORWARD==dir) {
212  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
213  if (*li==cb) {
214  list.erase(li);
215  return true;
216  }
217  }
218  } else {
219  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
220  if (*li==cb) {
221  list.erase((++li).base());
222  return true;
223  }
224  }
225  }
226  return false;
227  }
228 
233  List& clear() {
234  boost::lock_guard<boost::mutex> lock(mutex_);
235  list.clear();
236  return *this;
237  }
238 
242  std::list<CallbackType*> callbacks() const {
243  boost::lock_guard<boost::mutex> lock(mutex_);
244  return list;
245  }
246 
257  template<class ArgumentType>
258  bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const {
259  CBList list = callbacks(); /* copy, so callbacks can safely modify this object's list */
260  if (FORWARD==dir) {
261  for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
262  b = (**li)(b, args);
263  }
264  } else {
265  for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
266  b = (**li)(b, args);
267  }
268  }
269  return b;
270  }
271  };
272 }
273 
274 #endif /* ROSE_callbacks_H */
T CallbackType
Functor class.
Definition: callbacks.h:82
User callbacks.
Definition: callbacks.h:9
List & clear()
Remove all callbacks from list without destroying them.
Definition: callbacks.h:233
List & append(CallbackType *cb)
Append a functor to the end of the list without copying it.
Definition: callbacks.h:122
List & after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1))
Insert a callback after another.
Definition: callbacks.h:146
List of callback functors.
Definition: callbacks.h:80
bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const
Invokes all functors in the callback list.
Definition: callbacks.h:258
Direction
Direction of callback list traversal.
Definition: callbacks.h:12
std::list< CallbackType * > callbacks() const
Returns a copy of the underlying STL vector of functors.
Definition: callbacks.h:242
List & before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1))
Insert a callback before another.
Definition: callbacks.h:163
size_t size() const
Returns the number of callbacks in the list.
Definition: callbacks.h:104
Traverse the list from back to front.
Definition: callbacks.h:14
Traverse the list from front to back.
Definition: callbacks.h:13
List & replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements=(size_t)(-1), Direction dir=FORWARD)
Replace one callback with another.
Definition: callbacks.h:182
bool empty() const
Predicate to test whether the list is empty.
Definition: callbacks.h:112
std::list< CallbackType * > CBList
Standard vector of functor pointers.
Definition: callbacks.h:83
List & prepend(CallbackType *cb)
Prepend callback to beginning of list without copying it.
Definition: callbacks.h:134
bool erase(CallbackType *cb, Direction dir=FORWARD)
Remove a callback from a list without destroying it.
Definition: callbacks.h:209