00001
00002
00003
00004
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 ¬ification_source)
00274
00275 {
00276 NotificationSource_* source_ptr = NotificationManager().findSource((void*)¬ification_source);
00277
00278 if (source_ptr != 0)
00279 {
00280 source_ptr->enable();
00281 }
00282 }
00283
00284 template <class NotificationSource>
00285 inline void NotificationSourceDisable(NotificationSource ¬ification_source)
00286
00287 {
00288 NotificationSource_* source_ptr = NotificationManager().findSource((void*)¬ification_source);
00289
00290 if (source_ptr != 0)
00291 {
00292 source_ptr->disable();
00293 }
00294 }
00295
00296 template <class NotificationSource>
00297 inline bool NotificationSourceIsEnabled(NotificationSource ¬ification_source)
00298
00299 {
00300 return (NotificationManager().findEnabledSource((void*)¬ification_source) != 0);
00301 }
00302
00303 template <class NotificationSource>
00304 inline bool NotificationSourceIsDisabled(NotificationSource ¬ification_source)
00305
00306 {
00307 return (NotificationManager().findEnabledSource((void*)¬ification_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 ¬ification_source,
00429 const NotificationTarget ¬ification_target,
00430 const T1 &, const T2 &)
00431
00432 {
00433 NotificationManager().insert
00434 ((void*)¬ification_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 ¬ification_source)
00443
00444 {
00445 NotificationManager().remove((void*)¬ification_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 ¬ification_source,
00458 const NotificationTarget ¬ification_target,
00459 const T1 &)
00460
00461 {
00462 NotificationManager().remove((void*)¬ification_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 ¬ification_source,
00469 const NotificationTarget ¬ification_target,
00470 const T1& , const T2& )
00471
00472 {
00473 NotificationManager().remove
00474 ((void*)¬ification_source,
00475 (void*)&(NotificationTarget2<NotificationSource, T1, T2> &)notification_target);
00476 }
00477
00478 template <class NotificationSource>
00479 inline bool NotificationIsRegistered(const NotificationSource ¬ification_source)
00480
00481 {
00482 return NotificationManager().isInserted((void*)¬ification_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 ¬ification_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*)¬ification_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 ¬ification_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*)¬ification_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*)¬ification_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 }
00594
00595 #endif // BALL_CONCEPT_NOTIFICATION_H