2 // This file is part of the aMule Project.
4 // Copyright (C) 2005-2008 Mikkel Schubert ( xaignar@users.sourceforge.net )
5 // Copyright (C) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "OtherFunctions.h" // Needed for CMutexUnlocker
35 template <typename TEST
> class CObservable
;
39 * This class implements the observable part of an Observer/Observable pattern.
41 * The EventType paramter is used to specify a protocol for the event-type used
42 * by a particular Observer/Observable set and allows for any level of
43 * information passing to be used, depending on the context.
45 * In order to simplify matters for subclasses, both the Observer and the
46 * Observable class keep track of which objects are observing what, so that
47 * instances can safely be created and destroyed without having to manually
48 * keep the observers and observables in sync.
50 template <typename EventType
>
53 friend class CObservable
<EventType
>;
55 typedef CObservable
<EventType
> ObservableType
;
60 * All observables which has this object registered are notified
61 * as to avoid dangling pointers. This will not result in actual
69 * This function is called when an observed subject publishes an event.
71 * @param o The publisher of the event.
72 * @param e The actual event.
74 virtual void ReceiveNotification( const ObservableType
* o
, const EventType
& e
) = 0;
78 //! Mutex used to make access to the list of observed objects thread safe.
81 typedef std::set
<ObservableType
*> ObservableSetType
;
82 //! List of objects being observed.
83 ObservableSetType m_list
;
89 * This class implements the Observable part of the Observer/Observable pattern.
91 template <typename EventType
>
94 friend class CObserver
<EventType
>;
97 //! The observer-type accepted by this class
98 typedef CObserver
<EventType
> ObserverType
;
104 virtual ~CObservable();
108 * This function subscribes an observer to events from this observable.
110 * @param o The observer that wishes to observe this object.
111 * @return True if it succesfully subscribed, false otherwise.
113 * If the subscription was succesful, ObserverAdded() will be called
114 * on "o", allowing the subclass to initialize the the observer's state.
116 bool AddObserver( ObserverType
* o
);
119 * This function removes an observer from the list of subscribers.
121 * @param o The observer to unsubscribe from this observable.
122 * @return True if the observer was removed, false otherwise.
124 * ObserverRemoved() will be called for the observer "o", allowing
125 * the subclass to take steps to avoid outdated data being kept.
127 bool RemoveObserver( ObserverType
* o
);
131 * This function notifies all or an specific observer of an event.
133 * @param e The event to be published.
134 * @param o A specific subscribing observer or NULL for all subscribers.
136 * The purpose of the second parameter is to allow notifications of
137 * specific observers when the ObserverAdded() or ObserverRemoved()
138 * functions are called and it should not be used outside of these
141 void NotifyObservers( const EventType
& e
, ObserverType
* o
= NULL
);
145 * This function removes all observers from this object.
147 * ObserverRemoved is called on each observer.
149 void RemoveAllObservers();
153 * This function is called when an observer has been added to the observable.
155 virtual void ObserverAdded( ObserverType
* ) {};
159 * This function is called when observers are removed from the observable.
161 * Exceptions to this are:
162 * - When the Observable is being destroyed.
163 * - When the Observer is being destroyed.
165 virtual void ObserverRemoved( ObserverType
* ) {};
169 //! Mutex used to ensure thread-safety of the basic operations.
172 typedef std::set
<ObserverType
*> ObserverSetType
;
173 typedef typename
ObserverSetType::iterator myIteratorType
;
175 //! Set of all observers subscribing to this observable.
176 ObserverSetType m_list
;
182 ///////////////////////////////////////////////////////////////////////////////
187 template <typename EventType
>
188 CObserver
<EventType
>::~CObserver()
190 wxMutexLocker
lock( m_mutex
);
192 while ( !m_list
.empty() ) {
193 ObservableType
* o
= *m_list
.begin();
196 wxMutexLocker
oLock(o
->m_mutex
);
197 o
->m_list
.erase( this );
200 m_list
.erase( m_list
.begin() );
205 template <typename EventType
>
206 CObservable
<EventType
>::~CObservable()
208 wxMutexLocker
lock( m_mutex
);
210 while ( !m_list
.empty() ) {
211 ObserverType
* o
= *m_list
.begin();
214 wxMutexLocker
oLock(o
->m_mutex
);
215 o
->m_list
.erase( this );
218 m_list
.erase( m_list
.begin() );
223 template <typename EventType
>
224 bool CObservable
<EventType
>::AddObserver( CObserver
<EventType
>* o
)
229 wxMutexLocker
lock(m_mutex
);
230 if ( !m_list
.insert( o
).second
) {
236 wxMutexLocker
oLock(o
->m_mutex
);
237 o
->m_list
.insert( this );
246 template <typename EventType
>
247 bool CObservable
<EventType
>::RemoveObserver( CObserver
<EventType
>* o
)
252 wxMutexLocker
lock(m_mutex
);
253 if ( !m_list
.erase( o
) ) {
259 wxMutexLocker
oLock(o
->m_mutex
);
260 o
->m_list
.erase( this );
263 ObserverRemoved( o
);
269 template <typename EventType
>
270 void CObservable
<EventType
>::NotifyObservers( const EventType
& e
, ObserverType
* o
)
272 wxMutexLocker
lock(m_mutex
);
275 o
->ReceiveNotification( this, e
);
277 myIteratorType it
= m_list
.begin();
278 for ( ; it
!= m_list
.end(); ) {
279 CMutexUnlocker
unlocker(m_mutex
);
280 (*it
++)->ReceiveNotification( this, e
);
286 template <typename EventType
>
287 void CObservable
<EventType
>::RemoveAllObservers()
289 wxMutexLocker
lock(m_mutex
);
291 while ( !m_list
.empty() ) {
292 ObserverType
* o
= *m_list
.begin();
293 m_list
.erase( m_list
.begin() );
294 CMutexUnlocker
unlocker(m_mutex
);
297 wxMutexLocker
oLock(o
->m_mutex
);
298 o
->m_list
.erase( this );
301 ObserverRemoved( o
);
307 // File_checked_for_headers