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