1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX
24 #define INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX
25 
26 #include <sal/config.h>
27 #include <boost/weak_ptr.hpp>
28 
29 namespace slideshow {
30 namespace internal {
31 
32 ////////////////////////////////////////////////////////////////////////////
33 
34 struct EmptyBase
35 {
EmptyGuardslideshow::internal::EmptyBase::EmptyGuard36     struct EmptyGuard{ explicit EmptyGuard(EmptyBase) {} };
37     struct EmptyClearableGuard
38     {
EmptyClearableGuardslideshow::internal::EmptyBase::EmptyClearableGuard39         explicit EmptyClearableGuard(EmptyBase) {}
clearslideshow::internal::EmptyBase::EmptyClearableGuard40         void clear() {}
resetslideshow::internal::EmptyBase::EmptyClearableGuard41         void reset() {}
42     };
43 
44     typedef EmptyGuard           Guard;
45     typedef EmptyClearableGuard ClearableGuard;
46 };
47 
48 class MutexBase
49 {
50 public:
51     struct Guard : public osl::MutexGuard
52     {
Guardslideshow::internal::MutexBase::Guard53         explicit Guard(MutexBase const& rBase) :
54             osl::MutexGuard(rBase.maMutex)
55         {}
56     };
57     struct ClearableGuard : public osl::ClearableMutexGuard
58     {
ClearableGuardslideshow::internal::MutexBase::ClearableGuard59         explicit ClearableGuard(MutexBase const& rBase) :
60             osl::ClearableMutexGuard(rBase.maMutex)
61         {}
62     };
63 
64     mutable osl::Mutex maMutex;
65 };
66 
67 ////////////////////////////////////////////////////////////////////////////
68 
69 template< typename result_type, typename ListenerTargetT > struct FunctionApply
70 {
applyslideshow::internal::FunctionApply71     template<typename FuncT> static bool apply(
72         FuncT           func,
73         ListenerTargetT const& rArg )
74     {
75         return func(rArg);
76     }
77 };
78 
79 template<typename ListenerTargetT> struct FunctionApply<void,ListenerTargetT>
80 {
applyslideshow::internal::FunctionApply81     template<typename FuncT> static bool apply(
82         FuncT                  func,
83         ListenerTargetT const& rArg )
84     {
85         func(rArg);
86         return true;
87     }
88 };
89 
90 ////////////////////////////////////////////////////////////////////////////
91 
92 template< typename ListenerT > struct ListenerOperations
93 {
94     /// Notify a single one of the listeners
95     template< typename ContainerT,
96               typename FuncT >
notifySingleListenerslideshow::internal::ListenerOperations97     static bool notifySingleListener( ContainerT& rContainer,
98                                       FuncT       func )
99     {
100         const typename ContainerT::const_iterator aEnd( rContainer.end() );
101 
102         // true: a handler in this queue processed the event
103         // false: no handler in this queue finally processed the event
104         return (std::find_if( rContainer.begin(),
105                               aEnd,
106                               func ) != aEnd);
107     }
108 
109     /// Notify all listeners
110     template< typename ContainerT,
111               typename FuncT >
notifyAllListenersslideshow::internal::ListenerOperations112     static bool notifyAllListeners( ContainerT& rContainer,
113                                     FuncT       func )
114     {
115         bool bRet(false);
116         typename ContainerT::const_iterator       aCurr( rContainer.begin() );
117         typename ContainerT::const_iterator const aEnd ( rContainer.end() );
118         while( aCurr != aEnd )
119         {
120             if( FunctionApply< typename FuncT::result_type,
121                                typename ContainerT::value_type >::apply(
122                                    func,
123                                    *aCurr) )
124             {
125                 bRet = true;
126             }
127 
128             ++aCurr;
129         }
130 
131         // true: at least one handler returned true
132         // false: not a single handler returned true
133         return bRet;
134     }
135 
136     /// Prune container from deceased listeners
137     template< typename ContainerT >
pruneListenersslideshow::internal::ListenerOperations138     static void pruneListeners( ContainerT&, size_t )
139     {
140     }
141 };
142 
143 // specializations for weak_ptr
144 // ----------------------------
145 template< typename ListenerTargetT >
146 struct ListenerOperations< boost::weak_ptr<ListenerTargetT> >
147 {
148     template< typename ContainerT,
149               typename FuncT >
notifySingleListenerslideshow::internal::ListenerOperations150     static bool notifySingleListener( ContainerT& rContainer,
151                                       FuncT       func )
152     {
153         typename ContainerT::const_iterator       aCurr( rContainer.begin() );
154         typename ContainerT::const_iterator const aEnd ( rContainer.end() );
155         while( aCurr != aEnd )
156         {
157             boost::shared_ptr<ListenerTargetT> pListener( aCurr->lock() );
158 
159             if( pListener && func(pListener) )
160                 return true;
161 
162             ++aCurr;
163         }
164 
165         return false;
166     }
167 
168     template< typename ContainerT,
169               typename FuncT >
notifyAllListenersslideshow::internal::ListenerOperations170     static bool notifyAllListeners( ContainerT& rContainer,
171                                     FuncT       func )
172     {
173         bool bRet(false);
174         typename ContainerT::const_iterator       aCurr( rContainer.begin() );
175         typename ContainerT::const_iterator const aEnd ( rContainer.end() );
176         while( aCurr != aEnd )
177         {
178             boost::shared_ptr<ListenerTargetT> pListener( aCurr->lock() );
179 
180             if( pListener.get() &&
181                 FunctionApply< typename FuncT::result_type,
182                                boost::shared_ptr<ListenerTargetT> >::apply(func,pListener) )
183             {
184                 bRet = true;
185             }
186 
187             ++aCurr;
188         }
189 
190         return bRet;
191     }
192 
193     template< typename ContainerT >
pruneListenersslideshow::internal::ListenerOperations194     static void pruneListeners( ContainerT& rContainer,
195                                 size_t      nSizeThreshold )
196     {
197         if( rContainer.size() <= nSizeThreshold )
198             return;
199 
200         ContainerT aAliveListeners;
201         aAliveListeners.reserve(rContainer.size());
202 
203         typename ContainerT::const_iterator       aCurr( rContainer.begin() );
204         typename ContainerT::const_iterator const aEnd ( rContainer.end() );
205         while( aCurr != aEnd )
206         {
207             if( !aCurr->expired() )
208                 aAliveListeners.push_back( *aCurr );
209 
210             ++aCurr;
211         }
212 
213         std::swap( rContainer, aAliveListeners );
214     }
215 };
216 
217 } // namespace internal
218 } // namespace Presentation
219 
220 #endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX */
221 
222