1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
27 #include "listenercontainerimpl.hxx"
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).
38 Type for the listener objects to be held
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
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
;
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.
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
85 const typename
container_type::const_iterator
aEnd( maListeners
.end() );
86 if( std::find( maListeners
.begin(),
90 return true; // already added
101 @return false, if the listener is already added, true
104 bool add( listener_type
const& rListener
)
109 if( isAdded(rListener
) )
110 return false; // already added
112 maListeners
.push_back( rListener
);
114 ListenerOperations
<ListenerT
>::pruneListeners(
116 MaxDeceasedListenerUllage
);
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.
132 @return false, if the listener is already added, true
135 bool addSorted( listener_type
const& rListener
)
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 )
150 boost::prior(maListeners
.end()),
154 ListenerOperations
<ListenerT
>::pruneListeners(
156 MaxDeceasedListenerUllage
);
161 /** Remove listener from container
164 The listener to remove
166 @return false, if listener not found in container, true
169 bool remove( listener_type
const& rListener
)
173 const typename
container_type::iterator
aEnd( maListeners
.end() );
174 typename
container_type::iterator aIter
;
175 if( (aIter
=std::remove(maListeners
.begin(),
177 rListener
)) == aEnd
)
179 return false; // listener not found
182 maListeners
.erase( aIter
, aEnd
);
187 /// Removes all listeners in one go
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.
202 Given functor is called with listeners, until it returns true
204 @return true, if functor was successfully applied to a
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
);
217 ListenerOperations
<ListenerT
>::notifySingleListener(
222 Guard
aGuard2(*this);
223 ListenerOperations
<ListenerT
>::pruneListeners(
224 const_cast<container_type
&>(maListeners
),
225 MaxDeceasedListenerUllage
);
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.
238 Given functor is called with listeners.
240 @return true, if functor was successfully applied to at least
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
);
253 ListenerOperations
<ListenerT
>::notifyAllListeners(
258 Guard
aGuard2(*this);
259 ListenerOperations
<ListenerT
>::pruneListeners(
260 const_cast<container_type
&>(maListeners
),
261 MaxDeceasedListenerUllage
);
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
280 template< typename ListenerT
,
281 typename ContainerT
=std::vector
<ListenerT
> >
282 class ThreadSafeListenerContainer
: public ListenerContainerBase
<ListenerT
,
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
,
303 } // namespace internal
304 } // namespace slideshow
306 #endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX */
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */