1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: listenercontainer.hxx,v $
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>
38 #include "listenercontainerimpl.hxx"
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).
49 Type for the listener objects to be held
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
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
;
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.
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
96 const typename
container_type::const_iterator
aEnd( maListeners
.end() );
97 if( std::find( maListeners
.begin(),
101 return true; // already added
112 @return false, if the listener is already added, true
115 bool add( listener_type
const& rListener
)
120 if( isAdded(rListener
) )
121 return false; // already added
123 maListeners
.push_back( rListener
);
125 ListenerOperations
<ListenerT
>::pruneListeners(
127 MaxDeceasedListenerUllage
);
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.
143 @return false, if the listener is already added, true
146 bool addSorted( listener_type
const& rListener
)
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 )
161 boost::prior(maListeners
.end()),
165 ListenerOperations
<ListenerT
>::pruneListeners(
167 MaxDeceasedListenerUllage
);
172 /** Remove listener from container
175 The listener to remove
177 @return false, if listener not found in container, true
180 bool remove( listener_type
const& rListener
)
184 const typename
container_type::iterator
aEnd( maListeners
.end() );
185 typename
container_type::iterator aIter
;
186 if( (aIter
=std::remove(maListeners
.begin(),
188 rListener
)) == aEnd
)
190 return false; // listener not found
193 maListeners
.erase( aIter
, aEnd
);
198 /// Removes all listeners in one go
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.
213 Given functor is called with listeners, until it returns true
215 @return true, if functor was successfully applied to a
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
);
228 ListenerOperations
<ListenerT
>::notifySingleListener(
233 Guard
aGuard2(*this);
234 ListenerOperations
<ListenerT
>::pruneListeners(
235 const_cast<container_type
&>(maListeners
),
236 MaxDeceasedListenerUllage
);
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.
249 Given functor is called with listeners.
251 @return true, if functor was successfully applied to at least
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
);
264 ListenerOperations
<ListenerT
>::notifyAllListeners(
269 Guard
aGuard2(*this);
270 ListenerOperations
<ListenerT
>::pruneListeners(
271 const_cast<container_type
&>(maListeners
),
272 MaxDeceasedListenerUllage
);
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
291 template< typename ListenerT
,
292 typename ContainerT
=std::vector
<ListenerT
> >
293 class ThreadSafeListenerContainer
: public ListenerContainerBase
<ListenerT
,
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
,
314 } // namespace internal
315 } // namespace slideshow
317 #endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX */