1 /*
2  * The Doomsday Engine Project -- libcore
3  *
4  * Copyright © 2004-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
5  *
6  * @par License
7  * LGPL: http://www.gnu.org/licenses/lgpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15  * General Public License for more details. You should have received a copy of
16  * the GNU Lesser General Public License along with this program; if not, see:
17  * http://www.gnu.org/licenses</small>
18  */
19 
20 #ifndef LIBDENG2_OBSERVERS_H
21 #define LIBDENG2_OBSERVERS_H
22 
23 #include "../libcore.h"
24 #include "../Lockable"
25 #include "../Guard"
26 #include "../PointerSet"
27 
28 #include <QSet>
29 
30 /**
31  * Macro that forms the name of an observer interface.
32  */
33 #define DENG2_AUDIENCE_INTERFACE(Name) \
34     I##Name##Observer
35 
36 /**
37  * Macro for declaring an observer interface containing one method.
38  *
39  * @param Name    Name of the audience. E.g., "Deletion" produces @c DeletionAudience.
40  * @param Method  The pure virtual method that the observer has to implement.
41  *                The @c virtual keyword and <code>=0</code> are automatically included.
42  */
43 #define DENG2_DECLARE_AUDIENCE(Name, Method) \
44     class DENG2_AUDIENCE_INTERFACE(Name) : public de::ObserverBase { \
45     public: \
46         virtual ~DENG2_AUDIENCE_INTERFACE(Name)() {} \
47         virtual Method = 0; \
48     };
49 
50 /**
51  * Defines an audience. Typically used inside a class to define the observers
52  * as a public member variable (used by DENG_DEFINE_AUDIENCE). Produces a
53  * member variable called "audienceFor{Name}".
54  *
55  * @param Name  Name of the audience.
56  */
57 #define DENG2_AUDIENCE(Name) \
58     typedef de::Observers<DENG2_AUDIENCE_INTERFACE(Name)> Name##Audience; \
59     Name##Audience audienceFor##Name;
60 
61 #define DENG2_EXTERN_AUDIENCE(Name) \
62     typedef de::Observers<DENG2_AUDIENCE_INTERFACE(Name)> Name##Audience; \
63     DENG2_PUBLIC extern Name##Audience audienceFor##Name;
64 
65 #define DENG2_DECLARE_AUDIENCE_METHOD(Name) \
66     typedef de::Observers<DENG2_AUDIENCE_INTERFACE(Name)> Name##Audience; \
67     Name##Audience &audienceFor##Name(); \
68     Name##Audience const &audienceFor##Name() const;
69 
70 #define DENG2_AUDIENCE_METHOD(ClassName, Name) \
71     ClassName::Name##Audience &ClassName::audienceFor##Name() { return d->audienceFor##Name; } \
72     ClassName::Name##Audience const &ClassName::audienceFor##Name() const { return d->audienceFor##Name; }
73 
74 #define DENG2_AUDIENCE_METHOD_INLINE(Name) \
75     typedef de::Observers<DENG2_AUDIENCE_INTERFACE(Name)> Name##Audience; \
76     Name##Audience _audienceFor##Name; \
77     Name##Audience &audienceFor##Name() { return _audienceFor##Name; } \
78     Name##Audience const &audienceFor##Name() const { return _audienceFor##Name; }
79 
80 #define DENG2_PIMPL_AUDIENCE(Name) \
81     Name##Audience audienceFor##Name;
82 
83 /**
84  * Macro for defining an observer interface containing a single method.
85  *
86  * @param Name    Name of the audience. E.g., "Deletion" produces @c DeletionAudience
87  *                and @c audienceForDeletion.
88  * @param Method  The pure virtual method that the observer has to implement.
89  *                The @c virtual keyword and <code>=0</code> are automatically included.
90  */
91 #define DENG2_DEFINE_AUDIENCE(Name, Method) \
92     DENG2_DECLARE_AUDIENCE(Name, Method) \
93     DENG2_AUDIENCE(Name)
94 
95 #define DENG2_DEFINE_AUDIENCE2(Name, Method) \
96     DENG2_DECLARE_AUDIENCE(Name, Method) \
97     DENG2_DECLARE_AUDIENCE_METHOD(Name)
98 
99 #define DENG2_DEFINE_AUDIENCE_INLINE(Name, Method) \
100     DENG2_DECLARE_AUDIENCE(Name, Method) \
101     DENG2_AUDIENCE_METHOD_INLINE(Name)
102 
103 /**
104  * Macro that can be used in class declarations to specify which audiences the class
105  * can belong to.
106  *
107  * @param Type      Name of the type where the audience is defined.
108  * @param Audience  Audience name.
109  */
110 #define DENG2_OBSERVES(Type, Audience) public Type::I##Audience##Observer
111 
112 /**
113  * Macro for looping through all observers. @note The @a Audience type needs to be defined
114  * in the scope.
115  *
116  * @param SetName  Name of the observer set class.
117  * @param Var      Variable used in the loop.
118  * @param Name     Name of the observer set.
119  */
120 #define DENG2_FOR_EACH_OBSERVER(SetName, Var, Name) for (SetName::Loop Var(Name); !Var.done(); ++Var)
121 
122 /**
123  * Macro for looping through the audience members.
124  *
125  * @param Name  Name of the audience.
126  * @param Var   Variable used in the loop.
127  */
128 #define DENG2_FOR_AUDIENCE(Name, Var) \
129     DENG2_FOR_EACH_OBSERVER(Name##Audience, Var, audienceFor##Name)
130 
131 #define DENG2_FOR_AUDIENCE2(Name, Var) \
132     DENG2_FOR_EACH_OBSERVER(Name##Audience, Var, audienceFor##Name())
133 
134 /**
135  * Macro for looping through the public audience members from inside a private
136  * implementation.
137  *
138  * @param Name  Name of the audience.
139  * @param Var   Variable used in the loop.
140  */
141 #define DENG2_FOR_PUBLIC_AUDIENCE(Name, Var) \
142     DENG2_FOR_EACH_OBSERVER(Name##Audience, Var, self().audienceFor##Name)
143 
144 #define DENG2_FOR_PUBLIC_AUDIENCE2(Name, Var) \
145     DENG2_FOR_EACH_OBSERVER(Name##Audience, Var, self().audienceFor##Name())
146 
147 namespace de {
148 
149 class ObserverBase;
150 
151 /**
152  * Interface for a group of observers.
153  */
154 class DENG2_PUBLIC IAudience
155 {
156 public:
157     virtual ~IAudience();
158     virtual void addMember   (ObserverBase *member) = 0;
159     virtual void removeMember(ObserverBase *member) = 0;
160 };
161 
162 class DENG2_PUBLIC ObserverBase
163 {
164 public:
165     ObserverBase();
166     ObserverBase(ObserverBase const &) = delete; // copying denied
167     virtual ~ObserverBase();
168 
169     void addMemberOf   (IAudience &observers);
170     void removeMemberOf(IAudience &observers);
171 
172 private:
173     LockableT<PointerSetT<IAudience>> _memberOf;
174 };
175 
176 /**
177  * Template for observer sets. The template type should be an interface
178  * implemented by all the observers. The observer type must implement ObserverBase.
179  * @ingroup data
180  *
181  * @par How to use the non-pimpl audience macros
182  *
183  * These examples explain how to create an audience called "Deletion". In
184  * general, audience names should be nouns like this so they can be used in the
185  * form "audience for (something)".
186  *
187  * In a class declaration, define the audience in the @c public section of the
188  * class: <pre>DENG2_DEFINE_AUDIENCE(Deletion, ...interface-function...)</pre>
189  *
190  * This will generate a public member variable called @c audienceForDeletion
191  * that can be directly manipulated by other objects.
192  *
193  * Note that because the audience is created as a public member variable, this
194  * can easily lead to ABI backwards compatibility issues down the road if there
195  * is need to make changes to the class.
196  *
197  * @par How to use the pimpl audience macros
198  *
199  * Another set of macros is provided for declaring and defining a
200  * pimpl-friendly audience. The caveat is that you'll need to separately
201  * declare accessor methods and define the audience inside the private
202  * implementation of the class.
203  *
204  * First, define the audience in the @c public section of the class:
205  * <pre>DENG2_DEFINE_AUDIENCE2(Deletion, ...interface-function...)</pre>
206  *
207  * This works like DENG2_DEFINE_AUDIENCE, but without a public member variable.
208  * Instead, accessor methods are declared for accessing the audience.
209  *
210  * Then, inside the private implementation (@c Instance struct), define the
211  * audience: <pre>DENG2_PIMPL_AUDIENCE(Deletion)</pre>
212  *
213  * Finally, define the accessor methods (for instance, just before the
214  * constructor of the class):
215  * <pre>DENG2_AUDIENCE_METHOD(ClassName, Deletion)</pre>
216  *
217  * It is recommended to keep the DENG2_PIMPL_AUDIENCE and DENG2_AUDIENCE_METHOD
218  * macros close together in the source file for easier maintenance. The former
219  * could be at the end of the @c Instance struct while the latter is immediately
220  * following the struct.
221  *
222  * @par Thread-safety
223  *
224  * Observers and Observers::Loop lock the observer set separately for reading
225  * and writing as appropriate.
226  */
227 template <typename Type>
228 class Observers : public Lockable, public IAudience
229 {
230 public:
231     typedef PointerSetT<Type> Members; // note: ordered, array-based
232     typedef typename Members::const_iterator const_iterator;
233     typedef int size_type;
234 
235     /**
236      * Iteration utility for observers. This should be used when
237      * notifying observers, because it is safe against the observer removing
238      * itself from the observer set, or the set itself being destroyed.
239      */
240     class Loop : public PointerSet::IIterationObserver {
241     public:
Loop(Observers const & observers)242         Loop(Observers const &observers) : _audience(&observers)
243                                          , _prevObserver(nullptr) {
244             DENG2_GUARD(_audience);
245             if (members().flags() & PointerSet::AllowInsertionDuringIteration) {
246                 _prevObserver = members().iterationObserver();
247                 members().setIterationObserver(this);
248             }
249             members().setBeingIterated(true);
250             _next = members().begin();
251             next();
252         }
~Loop()253         virtual ~Loop() {
254             DENG2_GUARD(_audience);
255             members().setBeingIterated(false);
256             if (members().flags() & PointerSet::AllowInsertionDuringIteration) {
257                 members().setIterationObserver(_prevObserver);
258             }
259         }
done()260         bool done() const {
261             return _current >= members().end();
262         }
next()263         void next() {
264             _current = _next;
265             if (_current < members().begin()) {
266                 _current = members().begin();
267                 if (_next < _current) _next = _current;
268             }
269             if (_next < members().end()) {
270                 ++_next;
271             }
272         }
get()273         const_iterator const &get() const {
274             return _current;
275         }
276         Type *operator -> () const {
277             return *get();
278         }
279         Loop &operator ++ () {
280             next();
281             return *this;
282         }
pointerSetIteratorsWereInvalidated(PointerSet::Pointer const * oldBase,PointerSet::Pointer const * newBase)283         void pointerSetIteratorsWereInvalidated(PointerSet::Pointer const *oldBase,
284                                                 PointerSet::Pointer const *newBase) override {
285             if (_prevObserver) {
286                 _prevObserver->pointerSetIteratorsWereInvalidated(oldBase, newBase);
287             }
288             _current = reinterpret_cast<const_iterator>(newBase) +
289                        (_current - reinterpret_cast<const_iterator>(oldBase));
290             _next    = reinterpret_cast<const_iterator>(newBase) +
291                        (_next    - reinterpret_cast<const_iterator>(oldBase));
292         }
293     private:
members()294         inline Members const &members() const {
295             return _audience->_members;
296         }
297         Observers const *_audience;
298         PointerSet::IIterationObserver *_prevObserver;
299         const_iterator _current;
300         const_iterator _next;
301     };
302 
303     friend class Loop;
304 
305 public:
Observers()306     Observers() {}
307 
Observers(Observers<Type> const & other)308     Observers(Observers<Type> const &other) {
309         *this = other;
310     }
311 
~Observers()312     virtual ~Observers() {
313         _disassociateAllMembers();
314         DENG2_GUARD(this);
315     }
316 
clear()317     void clear() {
318         DENG2_GUARD(this);
319         _disassociateAllMembers();
320         _members.clear();
321     }
322 
323     Observers<Type> &operator = (Observers<Type> const &other) {
324         if (this == &other) return *this;
325         DENG2_GUARD(other);
326         DENG2_GUARD(this);
327         _members = other._members;
328         for (Type *observer : _members) {
329             observer->addMemberOf(*this);
330         }
331         return *this;
332     }
333 
334     /// Add an observer into the set. The set does not receive
335     /// ownership of the observer instance.
add(Type * observer)336     void add(Type *observer) {
337         _add(observer);
338         observer->addMemberOf(*this);
339     }
340 
341     Observers<Type> &operator += (Type *observer) {
342         add(observer);
343         return *this;
344     }
345 
346     Observers<Type> &operator += (Type &observer) {
347         add(&observer);
348         return *this;
349     }
350 
351     Observers<Type> const &operator += (Type const *observer) const {
352         const_cast<Observers<Type> *>(this)->add(const_cast<Type *>(observer));
353         return *this;
354     }
355 
356     Observers<Type> const &operator += (Type const &observer) const {
357         const_cast<Observers<Type> *>(this)->add(const_cast<Type *>(&observer));
358         return *this;
359     }
360 
remove(Type * observer)361     void remove(Type *observer) {
362         _remove(observer);
363         observer->removeMemberOf(*this);
364     }
365 
366     Observers<Type> &operator -= (Type *observer) {
367         remove(observer);
368         return *this;
369     }
370 
371     Observers<Type> &operator -= (Type &observer) {
372         remove(&observer);
373         return *this;
374     }
375 
376     Observers<Type> const &operator -= (Type *observer) const {
377         const_cast<Observers<Type> *>(this)->remove(observer);
378         return *this;
379     }
380 
381     Observers<Type> const &operator -= (Type &observer) const {
382         const_cast<Observers<Type> *>(this)->remove(&observer);
383         return *this;
384     }
385 
size()386     size_type size() const {
387         DENG2_GUARD(this);
388         return _members.size();
389     }
390 
isEmpty()391     inline bool isEmpty() const {
392         return size() == 0;
393     }
394 
contains(Type const * observer)395     bool contains(Type const *observer) const {
396         DENG2_GUARD(this);
397         return _members.contains(const_cast<Type *>(observer));
398     }
399 
contains(Type const & observer)400     bool contains(Type const &observer) const {
401         DENG2_GUARD(this);
402         return _members.contains(const_cast<Type *>(&observer));
403     }
404 
405     /**
406      * Allows or denies addition of audience members while the audience is being
407      * iterated. By default, addition is not allowed. If additions are allowed, only one
408      * Loop can be iterating the audience at a time.
409      *
410      * @param yes  @c true to allow additions, @c false to deny.
411      */
setAdditionAllowedDuringIteration(bool yes)412     void setAdditionAllowedDuringIteration(bool yes) {
413         DENG2_GUARD(this);
414         _members.setFlags(Members::AllowInsertionDuringIteration, yes);
415     }
416 
417     // Implements IAudience.
addMember(ObserverBase * member)418     void addMember   (ObserverBase *member) { _add   (static_cast<Type *>(member)); }
removeMember(ObserverBase * member)419     void removeMember(ObserverBase *member) { _remove(static_cast<Type *>(member)); }
420 
421 private:
_disassociateAllMembers()422     void _disassociateAllMembers() {
423         for (Type *observer : _members) {
424             observer->removeMemberOf(*this);
425         }
426     }
427 
_add(Type * observer)428     void _add(Type *observer) {
429         DENG2_GUARD(this);
430         DENG2_ASSERT(observer != 0);
431         _members.insert(observer);
432     }
433 
_remove(Type * observer)434     void _remove(Type *observer) {
435         DENG2_GUARD(this);
436         _members.remove(observer);
437     }
438 
439     Members _members;
440 };
441 
442 } // namespace de
443 
444 #endif /* LIBDENG2_OBSERVERS_H */
445