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