Bump version to 4.1-6
[LibreOffice.git] / slideshow / source / inc / listenercontainer.hxx
blobb89a0145bd46d6cf8f24abec15a68aeb370ad9c5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
20 #define INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
22 #include <osl/mutex.hxx>
23 #include <boost/utility.hpp>
24 #include <algorithm>
25 #include <vector>
27 #include "listenercontainerimpl.hxx"
29 namespace slideshow {
30 namespace internal {
32 /** Container for objects that can be notified.
34 This templatized container holds listener objects, than can get
35 notified (by calling certain methods on them).
37 @tpl Listener
38 Type for the listener objects to be held
40 @tpl ContainerT
41 Full type of the container to store the listener objects. Defaults
42 to std::vector<ListenerT>
44 @tpl MaxDeceasedListenerUllage
45 Threshold, from which upwards the listener container gets
46 pruned. Avoids frequent copying of nearly empty containers.
48 @attention internal class, not to be used. functionality is
49 incomplete, please use the Thread(Un)safeListenerContainer types
50 from below
52 template< typename ListenerT,
53 typename MutexHolderBaseT,
54 typename ContainerT=std::vector<ListenerT>,
55 size_t MaxDeceasedListenerUllage=16 > class ListenerContainerBase : public MutexHolderBaseT
57 typedef typename MutexHolderBaseT::Guard Guard;
58 typedef typename MutexHolderBaseT::ClearableGuard ClearableGuard;
60 public:
61 typedef ListenerT listener_type;
62 typedef ContainerT container_type;
63 typedef MutexHolderBaseT mutex_type;
65 /** Check whether listener container is empty
67 @return true, if currently no listeners registered. Note that
68 in a multi-threaded scenario, without external synchronisation
69 to this object, the return value might become wrong at any time.
71 bool isEmpty() const
73 Guard aGuard(*this);
74 return maListeners.empty();
77 /** Check whether given listener is already added
79 @return true, if given listener is already added.
81 bool isAdded( listener_type const& rListener ) const
83 Guard aGuard(*this);
85 const typename container_type::const_iterator aEnd( maListeners.end() );
86 if( std::find( maListeners.begin(),
87 aEnd,
88 rListener ) != aEnd )
90 return true; // already added
93 return false;
96 /** Add new listener
98 @param rListener
99 Listener to add
101 @return false, if the listener is already added, true
102 otherwise
104 bool add( listener_type const& rListener )
106 Guard aGuard(*this);
108 // ensure uniqueness
109 if( isAdded(rListener) )
110 return false; // already added
112 maListeners.push_back( rListener );
114 ListenerOperations<ListenerT>::pruneListeners(
115 maListeners,
116 MaxDeceasedListenerUllage);
118 return true;
121 /** Add new listener into sorted container
123 The stored listeners are kept sorted (using this method
124 requires listener_type to have operator< defined on it). Make
125 sure to call addSorted() for <em>each</em> listener to add to
126 this container - sorting is performed under the assumption
127 that existing entries are already sorted.
129 @param rListener
130 Listener to add
132 @return false, if the listener is already added, true
133 otherwise
135 bool addSorted( listener_type const& rListener )
137 Guard aGuard(*this);
139 // ensure uniqueness
140 if( isAdded(rListener) )
141 return false; // already added
143 maListeners.push_back( rListener );
145 // a single entry does not need to be sorted
146 if( maListeners.size() > 1 )
148 std::inplace_merge(
149 maListeners.begin(),
150 boost::prior(maListeners.end()),
151 maListeners.end() );
154 ListenerOperations<ListenerT>::pruneListeners(
155 maListeners,
156 MaxDeceasedListenerUllage);
158 return true;
161 /** Remove listener from container
163 @param rListener
164 The listener to remove
166 @return false, if listener not found in container, true
167 otherwise
169 bool remove( listener_type const& rListener )
171 Guard aGuard(*this);
173 const typename container_type::iterator aEnd( maListeners.end() );
174 typename container_type::iterator aIter;
175 if( (aIter=std::remove(maListeners.begin(),
176 aEnd,
177 rListener)) == aEnd )
179 return false; // listener not found
182 maListeners.erase( aIter, aEnd );
184 return true;
187 /// Removes all listeners in one go
188 void clear()
190 Guard aGuard(*this);
192 maListeners.clear();
195 /** Apply functor to one listener
197 This method applies functor to one of the listeners. Starting
198 with the first entry of the container, the functor is called
199 with the listener entries, until it returns true.
201 @param func
202 Given functor is called with listeners, until it returns true
204 @return true, if functor was successfully applied to a
205 listener
207 template< typename FuncT > bool apply( FuncT func ) const
209 ClearableGuard aGuard(*this);
211 // generate a local copy of all handlers, to make method
212 // reentrant and thread-safe.
213 container_type const local( maListeners );
214 aGuard.clear();
216 const bool bRet(
217 ListenerOperations<ListenerT>::notifySingleListener(
218 local,
219 func ));
222 Guard aGuard2(*this);
223 ListenerOperations<ListenerT>::pruneListeners(
224 const_cast<container_type&>(maListeners),
225 MaxDeceasedListenerUllage);
228 return bRet;
231 /** Apply functor to all listeners
233 This method applies functor to all of the listeners. Starting
234 with the first entry of the container, the functor is called
235 with the listener entries.
237 @param func
238 Given functor is called with listeners.
240 @return true, if functor was successfully applied to at least
241 one listener
243 template< typename FuncT > bool applyAll( FuncT func ) const
245 ClearableGuard aGuard(*this);
247 // generate a local copy of all handlers, to make method
248 // reentrant and thread-safe.
249 container_type const local( maListeners );
250 aGuard.clear();
252 const bool bRet(
253 ListenerOperations<ListenerT>::notifyAllListeners(
254 local,
255 func ));
258 Guard aGuard2(*this);
259 ListenerOperations<ListenerT>::pruneListeners(
260 const_cast<container_type&>(maListeners),
261 MaxDeceasedListenerUllage);
264 return bRet;
267 private:
268 ContainerT maListeners;
271 ////////////////////////////////////////////////////////////////////////////
273 /** ListenerContainer variant that serialized access
275 This ListenerContainer is safe to use in a multi-threaded
276 context. It serializes access to the object, and avoids
277 dead-locking by releasing the object mutex before calling
278 listeners.
280 template< typename ListenerT,
281 typename ContainerT=std::vector<ListenerT> >
282 class ThreadSafeListenerContainer : public ListenerContainerBase<ListenerT,
283 MutexBase,
284 ContainerT>
288 ////////////////////////////////////////////////////////////////////////////
290 /** ListenerContainer variant that does not serialize access
292 This ListenerContainer version is not safe to use in a
293 multi-threaded scenario, but has less overhead.
295 template< typename ListenerT,
296 typename ContainerT=std::vector<ListenerT> >
297 class ThreadUnsafeListenerContainer : public ListenerContainerBase<ListenerT,
298 EmptyBase,
299 ContainerT>
303 } // namespace internal
304 } // namespace slideshow
306 #endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX */
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */