00001 #ifndef ROSE_Callbacks_H
00002 #define ROSE_Callbacks_H
00003
00004 #include "threadSupport.h"
00005 #include <list>
00006
00008 namespace ROSE_Callbacks {
00009
00011 enum Direction {
00012 FORWARD,
00013 BACKWARD
00014 };
00015
00078 template<class T>
00079 class List {
00080 public:
00081 typedef T CallbackType;
00082 typedef std::list<CallbackType*> CBList;
00084 List() {
00085 RTS_mutex_init(&mutex, RTS_LAYER_ROSE_CALLBACKS_LIST_OBJ, NULL);
00086 }
00087
00088 explicit List(CallbackType *callback) {
00089 RTS_mutex_init(&mutex, RTS_LAYER_ROSE_CALLBACKS_LIST_OBJ, NULL);
00090 append(callback);
00091 }
00092
00096 size_t size() const {
00097 size_t retval = 0;
00098 RTS_MUTEX(mutex) {
00099 retval = list.size();
00100 } RTS_MUTEX_END;
00101 return retval;
00102 }
00103
00107 bool empty() const {
00108 bool retval = false;
00109 RTS_MUTEX(mutex) {
00110 retval = list.empty();
00111 } RTS_MUTEX_END;
00112 return retval;
00113 }
00114
00120 List& append(CallbackType *cb) {
00121 RTS_MUTEX(mutex) {
00122 assert(cb!=NULL);
00123 list.push_back(cb);
00124 } RTS_MUTEX_END;
00125 return *this;
00126 }
00127
00133 List& prepend(CallbackType *cb) {
00134 RTS_MUTEX(mutex) {
00135 assert(cb!=NULL);
00136 list.push_front(cb);
00137 } RTS_MUTEX_END;
00138 return *this;
00139 }
00140
00146 List& after(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
00147 RTS_MUTEX(mutex) {
00148 assert(cb!=NULL);
00149 for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
00150 if (*li==relative_to) {
00151 li = list.insert(++li, cb);
00152 --nreplacements;
00153 }
00154 }
00155 } RTS_MUTEX_END;
00156 return *this;
00157 }
00158
00164 List& before(CallbackType *relative_to, CallbackType *cb, size_t nreplacements=(size_t)(-1)) {
00165 RTS_MUTEX(mutex) {
00166 assert(cb!=NULL);
00167 for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
00168 if (*li==relative_to) {
00169 li = list.insert(li, cb);
00170 ++li;
00171 --nreplacements;
00172 }
00173 }
00174 } RTS_MUTEX_END;
00175 return *this;
00176 }
00177
00184 List& replace(CallbackType *old_cb, CallbackType *new_cb, size_t nreplacements=(size_t)(-1), Direction dir=FORWARD) {
00185 RTS_MUTEX(mutex) {
00186 assert(new_cb!=NULL);
00187 if (FORWARD==dir) {
00188 for (typename CBList::iterator li=list.begin(); li!=list.end() && nreplacements>0; ++li) {
00189 if (*li==old_cb) {
00190 *li = new_cb;
00191 --nreplacements;
00192 }
00193 }
00194 } else {
00195 for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend() && nreplacements>0; ++li) {
00196 if (*li==old_cb) {
00197 *li = new_cb;
00198 --nreplacements;
00199 }
00200 }
00201 }
00202 } RTS_MUTEX_END;
00203 return *this;
00204 }
00205
00212 bool erase(CallbackType *cb, Direction dir=FORWARD) {
00213 bool erased = false;
00214 RTS_MUTEX(mutex) {
00215 if (FORWARD==dir) {
00216 for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
00217 if (*li==cb) {
00218 list.erase(li);
00219 erased = true;
00220 break;
00221 }
00222 }
00223 } else {
00224 for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
00225 if (*li==cb) {
00226 list.erase((++li).base());
00227 erased = true;
00228 break;
00229 }
00230 }
00231 }
00232 } RTS_MUTEX_END;
00233 return erased;
00234 }
00235
00240 List& clear() {
00241 RTS_MUTEX(mutex) {
00242 list.clear();
00243 } RTS_MUTEX_END;
00244 return *this;
00245 }
00246
00250 std::list<CallbackType*> callbacks() const {
00251 CBList retval;
00252 RTS_MUTEX(mutex) {
00253 retval = list;
00254 } RTS_MUTEX_END;
00255 return retval;
00256 }
00257
00268 template<class ArgumentType>
00269 bool apply(bool b, const ArgumentType &args, Direction dir=FORWARD) const {
00270 CBList list = callbacks();
00271 if (FORWARD==dir) {
00272 for (typename CBList::iterator li=list.begin(); li!=list.end(); ++li) {
00273 b = (**li)(b, args);
00274 }
00275 } else {
00276 for (typename CBList::reverse_iterator li=list.rbegin(); li!=list.rend(); ++li) {
00277 b = (**li)(b, args);
00278 }
00279 }
00280 return b;
00281 }
00282
00283 private:
00284 mutable RTS_mutex_t mutex;
00285 CBList list;
00286 };
00287 }
00288
00289 #endif