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