notification.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: notification.h,v 1.22 2005/07/16 21:00:29 oliver Exp $
00005 //
00006 
00007 #ifndef BALL_CONCEPT_NOTIFICATION_H
00008 #define BALL_CONCEPT_NOTIFICATION_H
00009 
00010 #ifndef BALL_COMMON_GLOBAL_H
00011 # include <BALL/COMMON/global.h>
00012 #endif
00013 
00014 #ifndef BALL_COMMON_RTTI_H
00015 # include <BALL/COMMON/rtti.h>
00016 #endif
00017 
00018 #define BALL_NOTIFICATION_MANAGER_GROWTH_THRESHOLD(slots)   (2 * (slots) - 1)
00019 
00020 namespace BALL 
00021 {
00022 
00032   
00033   class NotificationManager_;
00034   class NotificationSource_;
00035 
00037   class NotificationTarget_
00038   {
00039     friend class NotificationManager_;
00040     friend class NotificationSource_;
00041 
00042     public:
00043 
00045     ~NotificationTarget_()
00046       ;
00047 
00049     NotificationTarget_* getNextTarget()
00050       ;
00051 
00053     void* getTarget()
00054       ;
00055 
00056     private:
00057 
00059     NotificationTarget_()
00060       ;
00061 
00063     NotificationTarget_(NotificationTarget_* notification_target, void* target)
00064       ;
00065 
00066 
00067     NotificationTarget_*  next_;
00068     void*                 target_;
00069   };
00070 
00072   class NotificationSource_
00073   {
00074     friend class NotificationManager_;
00075 
00076     public:
00077 
00079     ~NotificationSource_()
00080       ;
00081 
00083     void enable()
00084       ;
00085   
00087     void disable()
00088       ;
00089 
00091     bool isEnabled()
00092       ;
00093   
00095     bool isDisabled()
00096       ;
00097 
00098   
00099     private:
00100 
00102     NotificationSource_()
00103       ;
00104 
00106     NotificationSource_(NotificationSource_* notification_source, void* source)
00107       ;
00108 
00110     void destroy()
00111       ;
00112 
00113     NotificationSource_*  next_;
00114     NotificationTarget_*  first_;
00115     void*                 source_;
00116     Size                  number_of_targets_;
00117     bool                  enabled_;
00118   };
00119 
00121   class NotificationSlot_
00122   {
00123     friend class NotificationManager_;
00124 
00125     public:
00126 
00128     ~NotificationSlot_()
00129       ;
00130 
00131 
00132     private:
00133 
00134     NotificationSlot_()
00135       ;
00136 
00137     NotificationSource_* first_;
00138   };
00139 
00141   class NotificationManager_
00142   {
00143     friend NotificationManager_& NotificationManager()
00144       ;
00145 
00146     public:
00147 
00149     static const Size INITIAL_NUMBER_OF_SLOTS;
00150 
00152     ~NotificationManager_()
00153       ;
00154 
00156     Size getSize()
00157       ;
00158 
00160     void insert(void* source, void* target)
00161       ;
00162 
00164     void remove(void* source)
00165       ;
00166 
00168     void remove(void* source, void* target)
00169       ;
00170 
00172     NotificationSource_* findSource(void* source)
00173       ;
00174 
00176     NotificationTarget_* findFirstTarget(void* source)
00177       ;
00178 
00180     NotificationTarget_* findTarget(void* source, void* target)
00181       ;
00182 
00184     NotificationSource_* findEnabledSource(void* source)
00185       ;
00186 
00188     NotificationTarget_* findEnabledFirstTarget(void* source)
00189       ;
00190 
00192     NotificationTarget_* findEnabledTarget(void* source, void* target)
00193       ;
00194 
00196     void destroy()
00197       ;
00198 
00200     void enable()
00201       ;
00202 
00204     void disable()
00205       ;
00206 
00208     bool isEnabled()
00209       ;
00210   
00212     bool isDisabled()
00213       ;
00214   
00216     bool isEmpty()
00217       ;
00218 
00220     bool isInserted(void* source)
00221       ;
00222 
00224     bool isInserted(void* source, void* target)
00225       ;
00226 
00228     void dump(std::ostream& s)
00229       ;
00230 
00231 
00232     private:
00233 
00234     NotificationManager_()
00235       ;
00236       
00237     bool needResize_()
00238       ;
00239 
00240     void resize_()
00241       ;
00242 
00243     Index hash_(void* ptr)
00244       ;
00245 
00246     Size                number_of_targets_;
00247     Size                number_of_slots_;
00248     NotificationSlot_*  slots_;
00249     bool                enabled_;
00250   };
00251 
00253   NotificationManager_& NotificationManager()
00254     ;
00255  
00257   void NotificationManagerEnable()
00258     ;
00259 
00261   void NotificationManagerDisable()
00262     ;
00263 
00265   bool NotificationManagerIsEnabled()
00266     ;
00267 
00269   bool NotificationManagerIsDisabled()
00270     ;
00271 
00272   template <class NotificationSource>
00273   inline void NotificationSourceEnable(NotificationSource &notification_source)
00274     
00275   {
00276     NotificationSource_* source_ptr = NotificationManager().findSource((void*)&notification_source);
00277 
00278     if (source_ptr != 0)
00279     {
00280       source_ptr->enable();
00281     }
00282   }
00283 
00284   template <class NotificationSource>
00285   inline void NotificationSourceDisable(NotificationSource &notification_source)
00286     
00287   {
00288     NotificationSource_* source_ptr = NotificationManager().findSource((void*)&notification_source);
00289 
00290     if (source_ptr != 0)
00291     {
00292       source_ptr->disable();
00293     }
00294   }
00295 
00296   template <class NotificationSource>
00297   inline bool NotificationSourceIsEnabled(NotificationSource &notification_source)
00298     
00299   {
00300     return (NotificationManager().findEnabledSource((void*)&notification_source) != 0);
00301   }
00302 
00303   template <class NotificationSource>
00304   inline bool NotificationSourceIsDisabled(NotificationSource &notification_source)
00305     
00306   {
00307     return (NotificationManager().findEnabledSource((void*)&notification_source) == 0);
00308   }
00309 
00310 
00313   template <class NotificationSource>
00314   class NotificationTarget
00315   {
00316     public:
00317     virtual ~NotificationTarget()  {}
00318 
00321     virtual bool onNotify(NotificationSource& source) = 0;
00322 
00325     virtual unsigned short countNotificationTypes_()
00326       
00327     {
00328       return 0;
00329     }
00330 
00333     static void* getNotificationType_()
00334       
00335     {
00336       return RTTI::getClassID<NotificationSource>();
00337     }
00338 
00341     virtual void* getVirtualNotificationType_()
00342       
00343     {
00344       return getNotificationType_();
00345     }
00346   };
00347 
00349   template <class NotificationSource, class T1>
00350   class NotificationTarget1
00351   {
00352     public:
00353 
00355     virtual bool onNotify(NotificationSource &, T1) = 0;
00356 
00358     virtual unsigned short countNotificationTypes_()
00359       
00360     {
00361       return 1;
00362     }
00363 
00365     static void* getNotificationType_()
00366       
00367     {
00368       return (void* )&getNotificationType_;
00369     }
00370 
00372     virtual void* getVirtualNotificationType()
00373       
00374     {
00375       return getNotificationType_();
00376     }
00377   };
00378 
00380   template <class NotificationSource, class T1, class T2>
00381   class NotificationTarget2
00382   {
00383     public:
00384 
00386     virtual bool onNotify(NotificationSource &, T1, T2) = 0;
00387 
00389     virtual unsigned short countNotificationTypes_()
00390       
00391     {
00392       return 2;
00393     }
00394 
00396     static void* getNotificationType_()
00397       
00398     {
00399       return (void* )&getNotificationType_;
00400     }
00401 
00403     virtual void* getVirtualNotificationType_()
00404       
00405     {
00406       return getNotificationType_();
00407     }
00408   };
00409 
00410 
00411 
00412   template <class Source, class Target>
00413   inline void NotificationRegister(const Source &source, const Target &target)
00414     
00415   {
00416     NotificationManager().insert((void*)&source, (void*)&(NotificationTarget<Source> &)target);
00417   }
00418 
00419   template <class Source, class Target, class T1>
00420   inline void NotificationRegister1(const Source& source, const Target& target, const T1 &)
00421     
00422   {
00423     NotificationManager().insert((void*)&source, (void*)&(NotificationTarget1<Source, T1> &)target);
00424   }
00425 
00426   template <class NotificationSource, class NotificationTarget, class T1, class T2>
00427   inline void NotificationRegister2
00428     (const NotificationSource &notification_source,
00429      const NotificationTarget &notification_target,
00430      const T1 &, const T2 &)
00431     
00432   {
00433     NotificationManager().insert
00434       ((void*)&notification_source, 
00435        (void*)&(NotificationTarget2<NotificationSource, T1, T2> &)notification_target);
00436   }
00437 
00438   void NotificationUnregisterAll()
00439     ;
00440 
00441   template <class NotificationSource>
00442   inline void NotificationUnregister(const NotificationSource &notification_source)
00443     
00444   {
00445     NotificationManager().remove((void*)&notification_source);
00446   }
00447 
00448   template <class Source, class Target>
00449   inline void NotificationUnregister(const Source &source, const Target &target)
00450     
00451   {
00452     NotificationManager().remove((void*)&source, (void*)&(NotificationTarget<Source> &)target);
00453   }
00454 
00455   template <class NotificationSource, class NotificationTarget, class T1>
00456   inline void NotificationUnregister1
00457     (const NotificationSource &notification_source,
00458      const NotificationTarget &notification_target,
00459      const T1 &)
00460     
00461   {
00462     NotificationManager().remove((void*)&notification_source, 
00463        (void*)&(NotificationTarget1<NotificationSource, T1> &)notification_target);
00464   }
00465 
00466   template <class NotificationSource, class NotificationTarget, class T1, class T2>
00467   inline void NotificationUnregister2
00468     (const NotificationSource &notification_source,
00469      const NotificationTarget &notification_target,
00470      const T1& , const T2& )
00471     
00472   {
00473     NotificationManager().remove
00474       ((void*)&notification_source, 
00475        (void*)&(NotificationTarget2<NotificationSource, T1, T2> &)notification_target);
00476   }
00477 
00478   template <class NotificationSource>
00479   inline bool NotificationIsRegistered(const NotificationSource &notification_source)
00480     
00481   {
00482     return NotificationManager().isInserted((void*)&notification_source);
00483   }
00484 
00485   template <class Source, class Target>
00486   inline bool NotificationIsRegistered(const Source& source, const Target& target)
00487     
00488   {
00489     return NotificationManager().isInserted((void*)&source, 
00490        (void*)&(NotificationTarget<Source> &)target);
00491   }
00492 
00493   template <class NotificationSource>
00494   bool Notify(NotificationSource &notification_source)
00495     
00496   {
00497     if (NotificationManager().isDisabled() == true)
00498     {
00499       return true;
00500     }
00501 
00502     NotificationTarget<NotificationSource>* notification_target0;
00503 
00504     for (NotificationTarget_* notification_target 
00505           = NotificationManager().findEnabledFirstTarget((void*)&notification_source);
00506          notification_target != 0;
00507          notification_target = notification_target->getNextTarget())
00508     {
00509       notification_target0 = (NotificationTarget<NotificationSource>* )notification_target->getTarget();
00510 
00511       if (notification_target0 != 0 && notification_target0->countNotificationTypes_() == 0
00512           && notification_target0->getVirtualNotificationType_() 
00513             == NotificationTarget<NotificationSource>::getNotificationType_())
00514       {
00515         if (notification_target0->onNotify(notification_source) == false)
00516         {
00517           return false;
00518         }
00519       }
00520     }
00521 
00522     return true;
00523   }
00524 
00525   template <class NotificationSource, class T1>
00526   bool Notify(NotificationSource &notification_source, const T1 &data1)
00527     
00528   {
00529     if (NotificationManager().isDisabled() == true)
00530     {
00531       return true;
00532     }
00533     
00534     NotificationTarget1<NotificationSource, T1>* notification_target1;
00535 
00536     for (NotificationTarget_* notification_target 
00537      = NotificationManager().findEnabledFirstTarget((void*)&notification_source);
00538          notification_target != 0;
00539          notification_target = notification_target->getNextTarget())
00540     {
00541       notification_target1
00542         = (NotificationTarget1<NotificationSource, T1>* )notification_target->getTarget();
00543 
00544       if (notification_target1 != 0
00545           && notification_target1->countNotificationTypes_() == 1
00546           && notification_target1->getVirtualNotificationType_() 
00547              == NotificationTarget1<NotificationSource, T1>::getNotificationType_())
00548       {
00549         if ((*notification_target1).onNotify(notification_source, data1) == false)
00550         {
00551           return false;
00552         }
00553       }
00554     }
00555 
00556     return true;
00557   }
00558 
00559   template <class NotificationSource, class T1, class T2>
00560   bool Notify (NotificationSource& notification_source, const T1& data1, const T2& data2)
00561     
00562   {
00563     if (NotificationManager().isDisabled())
00564     {
00565       return true;
00566     }
00567     
00568     NotificationTarget2<NotificationSource, T1, T2>* notification_target2;
00569 
00570     for (NotificationTarget_* notification_target 
00571            = NotificationManager().findEnabledFirstTarget((void*)&notification_source);
00572          notification_target != 0;
00573          notification_target = notification_target->getNextTarget())
00574     {
00575       notification_target2 = (NotificationTarget2<NotificationSource, T1, T2>* )notification_target->getTarget();
00576 
00577       if (notification_target2 != 0
00578           && notification_target2->countNotificationTypes_() == 2
00579           && notification_target2->getVirtualNotificationType_() 
00580            == NotificationTarget2<NotificationSource, T1, T2>::getNotificationType_())
00581       {
00582         if ((*notification_target2).onNotify(notification_source, data1, data2) == false)
00583         {
00584           return false;
00585         }
00586       }
00587     }
00588 
00589     return true;
00590   }
00591 
00593 } // namespace BALL
00594 
00595 #endif // BALL_CONCEPT_NOTIFICATION_H