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
26 #ifndef OBSERVABLEQUEUE_H
27 #define OBSERVABLEQUEUE_H
29 #include "Observable.h"
33 template <typename ValueType
>
38 * This class defines the protocol used by the CObservableQueue class.
40 * This specific protocol can be used by a class to make changes to its
41 * contents visible, assuming that said contents does not rely on being
42 * in a specific order, as insertions commands do not specify positions.
44 * The class CQueueObserver implements a queue that will always be kept
45 * in sync with the class observed, so that it is possible to handle all
46 * elements in a container object over a longer period of time, which
47 * would normally result in problems with changes accomulating in the list.
49 template <typename ValueType
>
53 //! The type of list used by this protocol to store values.
54 typedef std::vector
<ValueType
> ValueList
;
56 //! The events used by this observable type.
57 //! Note: If more than one instance of a value has been added, removed or
58 //! updated, then the resulting events should reflect this fact by
59 //! including the same of instances as has been changed.
61 //! Signals a QueueObserver that it has been added to a queue.
63 //! Signals a QueueObserver that it has been removed from a queue.
65 //! Signals that one or more values have been added.
67 //! Signals that one or more values have been removed.
69 //! Signals that the following values have been updated.
71 //! Signals that all values have been removed.
73 //! Contains the contents of the queue at subscription time.
79 * Constructor for misc events.
81 CQueueEvent( Type event
);
85 * Constructor for events regarding multiple values.
87 * Note: CQueueEvent does not take ownership of the specified list.
89 CQueueEvent( Type event
, const ValueList
* list
);
93 * Constructor for events regarding a single value
95 CQueueEvent( Type event
, const ValueType
& value
);
99 * Returns the event-type.
101 Type
GetEvent() const {
106 * Returns the number of available values passed with the event.
108 size_t GetCount() const;
111 * Returns a copy of the ith value.
113 ValueType
GetValue( size_t i
) const;
117 //! Pointer to a list of values. May be NULL.
118 const ValueList
* m_list
;
119 //! Pointer to a single value. May be NULL.
120 const ValueType
* m_value
;
121 //! The actual event-type.
128 * This class forms the superclass for observable queues or lists.
130 * The protocol defined above is used (CQueueEvent).
132 * By subclassing this class, a container object can ensure that classes
133 * observing it are able to keep in sync with the changes made to the
134 * contents, with a few limits.
136 * For one thing, the value is assumed to be both key and value, so
137 * multimaps cannot be used with this class, since it will only pass
138 * the key. Nor can lists that rely on a specific order be used, since
139 * neither insertion nor deletion operations specify a specific
140 * object or position, instead just a "add/remove one of these" rule.
142 * The main purpose of this class is to allow another class to follow
143 * a list or queue, regardles of changes in actual order of the items
144 * and regardles of changes to the contents.
146 template <typename ValueType
>
147 class CObservableQueue
: public CObservable
< CQueueEvent
<ValueType
> >
153 * Sends STOPPING to all observers.
155 virtual ~CObservableQueue();
158 typedef CQueueEvent
< ValueType
> EventType
;
159 typedef CObserver
< EventType
> ObserverType
;
160 typedef typename
EventType::ValueList ValueList
;
164 * Sends a STARTING event to new observers.
166 virtual void ObserverAdded( ObserverType
* );
169 * Sends a STOPPING event to removed observers.
171 virtual void ObserverRemoved( ObserverType
* );
177 * This class is an automatically synchronized queue connected with an ObservableQueue.
179 * Note that this observer can only be assigned to ONE observable at a time!
181 * This class implements a queue (out-order not specified) that allows an
182 * ObservableQueue object to be object to be used as a queue without making
183 * by another object in a safe manner. Changes to the contents of the original
184 * queue are propagated to this queue, such that it will never contain values
185 * not found in the original queue and such that it will add new values added
186 * to the original queue.
188 * This allows the contents to be accessed safely, when for instance it is
189 * needed to iterate over the contents over a period of time, where one
190 * cannot be certain of the current state of the actual contents of the
193 * This class supersedes such broken solutions such as remembering the last
194 * used position in the original list, since no changes made to the original
195 * list will result in items being skipped or treated twice*.
197 * * With the exception of the same item being removed and then re-added, in
198 * which case the CQueueObserver class will consider it a new item.
200 template <typename ValueType
>
201 class CQueueObserver
: public CObserver
< CQueueEvent
<ValueType
> >
204 typedef CQueueEvent
<ValueType
> EventType
;
205 typedef typename CObserver
< EventType
>::ObservableType ObservableType
;
206 typedef typename
EventType::ValueList ValueList
;
216 * Overloaded notification function.
218 virtual void ReceiveNotification( const ObservableType
*, const EventType
& e
);
222 * Returns the next element from the queue.
224 * Note: Objects will not be returned in the same order as
225 * they were found in the original observable. Also, note
226 * that calling GetNext() on an empty queue should only be
227 * done if the default contructed value does not match a
228 * valid object and can be used to check for End of Queue.
233 * Returns the number of remaining elements in the queue.
235 size_t GetRemaining() const;
238 * Returns true if the observer is currently assigned to an observable-queue.
240 bool IsActive() const;
243 * Clears the queue and readds itself to the current object being observed.
248 //! Lock used to ensure the threadsafety of the class
249 mutable wxMutex m_mutex
;
251 typedef std::multiset
<ValueType
> Queue
;
252 typedef typename
Queue::iterator QueueIterator
;
253 //! The remaining items.
256 //! Used to check that we are only subscribed to one queue at a time
257 const ObservableType
* m_owner
;
263 ///////////////////////////////////////////////////
268 template <typename ValueType
>
269 CQueueEvent
<ValueType
>::CQueueEvent( Type event
)
278 template <typename ValueType
>
279 CQueueEvent
<ValueType
>::CQueueEvent( Type event
, const ValueList
* list
)
288 template <typename ValueType
>
289 CQueueEvent
<ValueType
>::CQueueEvent( Type event
, const ValueType
& value
)
297 template <typename ValueType
>
298 size_t CQueueEvent
<ValueType
>::GetCount() const {
300 return m_list
->size();
301 } else if ( m_value
) {
309 template <typename ValueType
>
310 ValueType CQueueEvent
<ValueType
>::GetValue( size_t i
) const {
312 return (*m_list
).at( i
);
313 } else if ( m_value
&& i
== 0 ) {
324 template <typename ValueType
>
325 CObservableQueue
<ValueType
>::~CObservableQueue()
327 this->RemoveAllObservers();
331 template <typename ValueType
>
332 void CObservableQueue
<ValueType
>::ObserverAdded( ObserverType
* o
)
334 NotifyObservers( EventType( EventType::STARTING
), o
);
338 template <typename ValueType
>
339 void CObservableQueue
<ValueType
>::ObserverRemoved( ObserverType
* o
)
341 NotifyObservers( EventType( EventType::STOPPING
), o
);
347 template <typename ValueType
>
348 CQueueObserver
<ValueType
>::CQueueObserver()
354 template <typename ValueType
>
355 void CQueueObserver
<ValueType
>::ReceiveNotification( const ObservableType
* o
, const EventType
& e
)
357 wxMutexLocker
lock( m_mutex
);
359 if ( e
.GetEvent() == EventType::INSERTED
|| e
.GetEvent() == EventType::INITIAL
) {
360 for ( size_t i
= 0; i
< e
.GetCount(); i
++ ) {
361 m_queue
.insert( e
.GetValue( i
) );
363 } else if ( e
.GetEvent() == EventType::REMOVED
) {
364 for ( size_t i
= 0; i
< e
.GetCount(); i
++ ) {
365 QueueIterator it
= m_queue
.find( e
.GetValue( i
) );
367 if ( it
!= m_queue
.end() ) {
371 } else if ( e
.GetEvent() == EventType::CLEARED
) {
373 } else if ( e
.GetEvent() == EventType::STOPPING
) {
376 } else if ( e
.GetEvent() == EventType::STARTING
) {
377 wxASSERT(m_owner
== NULL
);
385 template <typename ValueType
>
386 ValueType CQueueObserver
<ValueType
>::GetNext()
388 wxMutexLocker
lock( m_mutex
);
390 if ( m_queue
.size() ) {
391 ValueType v
= *m_queue
.begin();
392 m_queue
.erase( m_queue
.begin() );
401 template <typename ValueType
>
402 size_t CQueueObserver
<ValueType
>::GetRemaining() const
404 wxMutexLocker
lock( m_mutex
);
406 return m_queue
.size();
410 template <typename ValueType
>
411 bool CQueueObserver
<ValueType
>::IsActive() const
413 return (m_owner
!= NULL
);
417 template <typename ValueType
>
418 void CQueueObserver
<ValueType
>::Reset()
420 ObservableType
* owner
;
423 wxMutexLocker
lock(m_mutex
);
425 owner
= const_cast<ObservableType
*>( m_owner
);
428 owner
->RemoveObserver( this );
429 owner
->AddObserver( this );
435 // File_checked_for_headers