1 | // |
2 | // NotificationCenter.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Notifications |
6 | // Module: NotificationCenter |
7 | // |
8 | // Definition of the NotificationCenter class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_NotificationCenter_INCLUDED |
18 | #define Foundation_NotificationCenter_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Notification.h" |
23 | #include "Poco/Mutex.h" |
24 | #include "Poco/SharedPtr.h" |
25 | #include <vector> |
26 | #include <cstddef> |
27 | |
28 | |
29 | namespace Poco { |
30 | |
31 | |
32 | class AbstractObserver; |
33 | |
34 | |
35 | class Foundation_API NotificationCenter |
36 | /// A NotificationCenter is essentially a notification dispatcher. |
37 | /// It notifies all observers of notifications meeting specific criteria. |
38 | /// This information is encapsulated in Notification objects. |
39 | /// Client objects register themselves with the notification center as observers of |
40 | /// specific notifications posted by other objects. When an event occurs, an object |
41 | /// posts an appropriate notification to the notification center. The notification |
42 | /// center invokes the registered method on each matching observer, passing the notification |
43 | /// as argument. |
44 | /// |
45 | /// The order in which observers receive notifications is undefined. |
46 | /// It is possible for the posting object and the observing object to be the same. |
47 | /// The NotificationCenter delivers notifications to observers synchronously. |
48 | /// In other words the postNotification() method does not return until all observers have |
49 | /// received and processed the notification. |
50 | /// If an observer throws an exception while handling a notification, the NotificationCenter |
51 | /// stops dispatching the notification and postNotification() rethrows the exception. |
52 | /// |
53 | /// In a multithreaded scenario, notifications are always delivered in the thread in which the |
54 | /// notification was posted, which may not be the same thread in which an observer registered itself. |
55 | /// |
56 | /// The NotificationCenter class is basically a C++ implementation of the NSNotificationCenter class |
57 | /// found in Apple's Cocoa (or OpenStep). |
58 | /// |
59 | /// While handling a notification, an observer can unregister itself from the notification center, |
60 | /// or it can register or unregister other observers. Observers added during a dispatch cycle |
61 | /// will not receive the current notification. |
62 | /// |
63 | /// The method receiving the notification must be implemented as |
64 | /// void handleNotification(MyNotification* pNf); |
65 | /// The handler method gets co-ownership of the Notification object |
66 | /// and must release it when done. This is best done with an AutoPtr: |
67 | /// void MyClass::handleNotification(MyNotification* pNf) |
68 | /// { |
69 | /// AutoPtr<MyNotification> nf(pNf); |
70 | /// ... |
71 | /// } |
72 | /// |
73 | /// Alternatively, the NObserver class template can be used to register a callback |
74 | /// method. In this case, the callback method receives the Notification in an |
75 | /// AutoPtr and thus does not have to deal with object ownership issues: |
76 | /// void MyClass::handleNotification(const AutoPtr<MyNotification>& pNf) |
77 | /// { |
78 | /// ... |
79 | /// } |
80 | { |
81 | public: |
82 | NotificationCenter(); |
83 | /// Creates the NotificationCenter. |
84 | |
85 | ~NotificationCenter(); |
86 | /// Destroys the NotificationCenter. |
87 | |
88 | void addObserver(const AbstractObserver& observer); |
89 | /// Registers an observer with the NotificationCenter. |
90 | /// Usage: |
91 | /// Observer<MyClass, MyNotification> obs(*this, &MyClass::handleNotification); |
92 | /// notificationCenter.addObserver(obs); |
93 | /// |
94 | /// Alternatively, the NObserver template class can be used instead of Observer. |
95 | |
96 | void removeObserver(const AbstractObserver& observer); |
97 | /// Unregisters an observer with the NotificationCenter. |
98 | |
99 | bool hasObserver(const AbstractObserver& observer) const; |
100 | /// Returns true if the observer is registered with this NotificationCenter. |
101 | |
102 | void postNotification(Notification::Ptr pNotification); |
103 | /// Posts a notification to the NotificationCenter. |
104 | /// The NotificationCenter then delivers the notification |
105 | /// to all interested observers. |
106 | /// If an observer throws an exception, dispatching terminates |
107 | /// and the exception is rethrown to the caller. |
108 | /// Ownership of the notification object is claimed and the |
109 | /// notification is released before returning. Therefore, |
110 | /// a call like |
111 | /// notificationCenter.postNotification(new MyNotification); |
112 | /// does not result in a memory leak. |
113 | |
114 | bool hasObservers() const; |
115 | /// Returns true iff there is at least one registered observer. |
116 | /// |
117 | /// Can be used to improve performance if an expensive notification |
118 | /// shall only be created and posted if there are any observers. |
119 | |
120 | std::size_t countObservers() const; |
121 | /// Returns the number of registered observers. |
122 | |
123 | static NotificationCenter& defaultCenter(); |
124 | /// Returns a reference to the default |
125 | /// NotificationCenter. |
126 | |
127 | private: |
128 | typedef SharedPtr<AbstractObserver> AbstractObserverPtr; |
129 | typedef std::vector<AbstractObserverPtr> ObserverList; |
130 | |
131 | ObserverList _observers; |
132 | mutable Mutex _mutex; |
133 | }; |
134 | |
135 | |
136 | } // namespace Poco |
137 | |
138 | |
139 | #endif // Foundation_NotificationCenter_INCLUDED |
140 | |