Upstream tarball 20080603
[amule.git] / src / Observable.h
blobe6858db68e2e42aa943db150c6cd2583e198ecfc
1 //
2 // This file is part of the aMule Project.
3 //
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 )
6 //
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
9 // respective authors.
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.
20 //
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
26 #ifndef OBSERVABLE_H
27 #define OBSERVABLE_H
30 #include <set>
32 #include "OtherFunctions.h" // Needed for CMutexUnlocker
35 template <typename TEST> class CObservable;
38 /**
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>
51 class CObserver
53 friend class CObservable<EventType>;
54 public:
55 typedef CObservable<EventType> ObservableType;
57 /**
58 * Destructor.
60 * All observables which has this object registered are notified
61 * as to avoid dangling pointers. This will not result in actual
62 * events.
64 virtual ~CObserver();
67 protected:
68 /**
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;
77 private:
78 //! Mutex used to make access to the list of observed objects thread safe.
79 wxMutex m_mutex;
81 typedef std::set<ObservableType*> ObservableSetType;
82 //! List of objects being observed.
83 ObservableSetType m_list;
88 /**
89 * This class implements the Observable part of the Observer/Observable pattern.
91 template <typename EventType>
92 class CObservable
94 friend class CObserver<EventType>;
96 public:
97 //! The observer-type accepted by this class
98 typedef CObserver<EventType> ObserverType;
102 * Destructor.
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 );
129 protected:
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
139 * functions.
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* ) {};
168 private:
169 //! Mutex used to ensure thread-safety of the basic operations.
170 wxMutex m_mutex;
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 )
226 wxASSERT( o );
229 wxMutexLocker lock(m_mutex);
230 if ( !m_list.insert( o ).second ) {
231 return false;
236 wxMutexLocker oLock(o->m_mutex);
237 o->m_list.insert( this );
240 ObserverAdded( o );
242 return true;
246 template <typename EventType>
247 bool CObservable<EventType>::RemoveObserver( CObserver<EventType>* o )
249 wxASSERT( o );
252 wxMutexLocker lock(m_mutex);
253 if ( !m_list.erase( o ) ) {
254 return false;
259 wxMutexLocker oLock(o->m_mutex);
260 o->m_list.erase( this );
263 ObserverRemoved( o );
265 return true;
269 template <typename EventType>
270 void CObservable<EventType>::NotifyObservers( const EventType& e, ObserverType* o )
272 wxMutexLocker lock(m_mutex);
274 if ( o ) {
275 o->ReceiveNotification( this, e );
276 } else {
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 );
306 #endif
307 // File_checked_for_headers