callbacks.h

Go to the documentation of this file.
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(); /* copy, so callbacks can safely modify this object's list */
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 /* ROSE_callbacks_H */

Generated on Wed May 16 06:17:53 2012 for ROSE by  doxygen 1.4.7