update dev300-m58
[ooovba.git] / slideshow / source / inc / listenercontainer.hxx
blob91e1105e6416ff76d90786795549428e233fb020
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: listenercontainer.hxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #ifndef INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
31 #define INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
33 #include <osl/mutex.hxx>
34 #include <boost/utility.hpp>
35 #include <algorithm>
36 #include <vector>
38 #include "listenercontainerimpl.hxx"
40 namespace slideshow {
41 namespace internal {
43 /** Container for objects that can be notified.
45 This templatized container holds listener objects, than can get
46 notified (by calling certain methods on them).
48 @tpl Listener
49 Type for the listener objects to be held
51 @tpl ContainerT
52 Full type of the container to store the listener objects. Defaults
53 to std::vector<ListenerT>
55 @tpl MaxDeceasedListenerUllage
56 Threshold, from which upwards the listener container gets
57 pruned. Avoids frequent copying of nearly empty containers.
59 @attention internal class, not to be used. functionality is
60 incomplete, please use the Thread(Un)safeListenerContainer types
61 from below
63 template< typename ListenerT,
64 typename MutexHolderBaseT,
65 typename ContainerT=std::vector<ListenerT>,
66 size_t MaxDeceasedListenerUllage=16 > class ListenerContainerBase : public MutexHolderBaseT
68 typedef typename MutexHolderBaseT::Guard Guard;
69 typedef typename MutexHolderBaseT::ClearableGuard ClearableGuard;
71 public:
72 typedef ListenerT listener_type;
73 typedef ContainerT container_type;
74 typedef MutexHolderBaseT mutex_type;
76 /** Check whether listener container is empty
78 @return true, if currently no listeners registered. Note that
79 in a multi-threaded scenario, without external synchronisation
80 to this object, the return value might become wrong at any time.
82 bool isEmpty() const
84 Guard aGuard(*this);
85 return maListeners.empty();
88 /** Check whether given listener is already added
90 @return true, if given listener is already added.
92 bool isAdded( listener_type const& rListener ) const
94 Guard aGuard(*this);
96 const typename container_type::const_iterator aEnd( maListeners.end() );
97 if( std::find( maListeners.begin(),
98 aEnd,
99 rListener ) != aEnd )
101 return true; // already added
104 return false;
107 /** Add new listener
109 @param rListener
110 Listener to add
112 @return false, if the listener is already added, true
113 otherwise
115 bool add( listener_type const& rListener )
117 Guard aGuard(*this);
119 // ensure uniqueness
120 if( isAdded(rListener) )
121 return false; // already added
123 maListeners.push_back( rListener );
125 ListenerOperations<ListenerT>::pruneListeners(
126 maListeners,
127 MaxDeceasedListenerUllage);
129 return true;
132 /** Add new listener into sorted container
134 The stored listeners are kept sorted (using this method
135 requires listener_type to have operator< defined on it). Make
136 sure to call addSorted() for <em>each</em> listener to add to
137 this container - sorting is performed under the assumption
138 that existing entries are already sorted.
140 @param rListener
141 Listener to add
143 @return false, if the listener is already added, true
144 otherwise
146 bool addSorted( listener_type const& rListener )
148 Guard aGuard(*this);
150 // ensure uniqueness
151 if( isAdded(rListener) )
152 return false; // already added
154 maListeners.push_back( rListener );
156 // a single entry does not need to be sorted
157 if( maListeners.size() > 1 )
159 std::inplace_merge(
160 maListeners.begin(),
161 boost::prior(maListeners.end()),
162 maListeners.end() );
165 ListenerOperations<ListenerT>::pruneListeners(
166 maListeners,
167 MaxDeceasedListenerUllage);
169 return true;
172 /** Remove listener from container
174 @param rListener
175 The listener to remove
177 @return false, if listener not found in container, true
178 otherwise
180 bool remove( listener_type const& rListener )
182 Guard aGuard(*this);
184 const typename container_type::iterator aEnd( maListeners.end() );
185 typename container_type::iterator aIter;
186 if( (aIter=std::remove(maListeners.begin(),
187 aEnd,
188 rListener)) == aEnd )
190 return false; // listener not found
193 maListeners.erase( aIter, aEnd );
195 return true;
198 /// Removes all listeners in one go
199 void clear()
201 Guard aGuard(*this);
203 maListeners.clear();
206 /** Apply functor to one listener
208 This method applies functor to one of the listeners. Starting
209 with the first entry of the container, the functor is called
210 with the listener entries, until it returns true.
212 @param func
213 Given functor is called with listeners, until it returns true
215 @return true, if functor was successfully applied to a
216 listener
218 template< typename FuncT > bool apply( FuncT func ) const
220 ClearableGuard aGuard(*this);
222 // generate a local copy of all handlers, to make method
223 // reentrant and thread-safe.
224 container_type const local( maListeners );
225 aGuard.clear();
227 const bool bRet(
228 ListenerOperations<ListenerT>::notifySingleListener(
229 local,
230 func ));
233 Guard aGuard2(*this);
234 ListenerOperations<ListenerT>::pruneListeners(
235 const_cast<container_type&>(maListeners),
236 MaxDeceasedListenerUllage);
239 return bRet;
242 /** Apply functor to all listeners
244 This method applies functor to all of the listeners. Starting
245 with the first entry of the container, the functor is called
246 with the listener entries.
248 @param func
249 Given functor is called with listeners.
251 @return true, if functor was successfully applied to at least
252 one listener
254 template< typename FuncT > bool applyAll( FuncT func ) const
256 ClearableGuard aGuard(*this);
258 // generate a local copy of all handlers, to make method
259 // reentrant and thread-safe.
260 container_type const local( maListeners );
261 aGuard.clear();
263 const bool bRet(
264 ListenerOperations<ListenerT>::notifyAllListeners(
265 local,
266 func ));
269 Guard aGuard2(*this);
270 ListenerOperations<ListenerT>::pruneListeners(
271 const_cast<container_type&>(maListeners),
272 MaxDeceasedListenerUllage);
275 return bRet;
278 private:
279 ContainerT maListeners;
282 ////////////////////////////////////////////////////////////////////////////
284 /** ListenerContainer variant that serialized access
286 This ListenerContainer is safe to use in a multi-threaded
287 context. It serializes access to the object, and avoids
288 dead-locking by releasing the object mutex before calling
289 listeners.
291 template< typename ListenerT,
292 typename ContainerT=std::vector<ListenerT> >
293 class ThreadSafeListenerContainer : public ListenerContainerBase<ListenerT,
294 MutexBase,
295 ContainerT>
299 ////////////////////////////////////////////////////////////////////////////
301 /** ListenerContainer variant that does not serialize access
303 This ListenerContainer version is not safe to use in a
304 multi-threaded scenario, but has less overhead.
306 template< typename ListenerT,
307 typename ContainerT=std::vector<ListenerT> >
308 class ThreadUnsafeListenerContainer : public ListenerContainerBase<ListenerT,
309 EmptyBase,
310 ContainerT>
314 } // namespace internal
315 } // namespace slideshow
317 #endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX */