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 24 #ifndef INCLUDED_O3TL_LAZY_UPDATE_HXX 25 #define INCLUDED_O3TL_LAZY_UPDATE_HXX 26 27 #include <sal/types.h> 28 #include <boost/function.hpp> 29 30 namespace o3tl 31 { 32 /** Update output object lazily 33 34 This template collects data in input type, and updates the 35 output type with the given update functor, but only if the 36 output is requested. Usef�l if updating is expensive, or input 37 changes frequently, but output is only comparatively seldom 38 used. 39 40 @example 41 <pre> 42 LazyUpdate<InType,OutType,LAZYUPDATE_DIRECT_TAG> myValue; 43 *myValue = newInput; 44 myValue->updateInput( this, that, those ); 45 46 output( *myValue ); 47 </pre> 48 or 49 <pre> 50 output( myValue.getOutValue() ); 51 </pre> 52 if the compiler does not recognize the const context. 53 */ 54 template< typename InputType, typename OutputType, typename Tag > class LazyUpdate; 55 56 /// LazyUpdate specialization takes boost::function argument 57 struct LAZYUPDATE_FUNCTOR_TAG {}; 58 /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument 59 struct LAZYUPDATE_FUNCTION_TAG {}; 60 /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument 61 struct LAZYUPDATE_DIRECT_TAG {}; 62 63 // ----------------------------------------------------------------------------------------------------- 64 65 namespace detail 66 { 67 /// @internal 68 template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor 69 { 70 public: 71 typedef OutputType output_type; 72 typedef InputType input_type; 73 LazyUpdateImpl()74 LazyUpdateImpl() : 75 m_aInput() 76 {} 77 LazyUpdateImpl(ParamType const & rParm)78 template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) : 79 Functor(rParm), 80 m_aInput() 81 {} 82 83 enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG }; LazyUpdateImpl(const input_type & rInput,UnaryConstructorTag)84 LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) : 85 m_aInput(rInput) 86 {} 87 LazyUpdateImpl(ParamType const & rParm,const input_type & rInput)88 template< typename ParamType > LazyUpdateImpl( ParamType const& rParm, 89 const input_type& rInput ) : 90 Functor(rParm), 91 m_aInput(rInput) 92 {} 93 94 // default copy ctor/assignment operator are ok 95 // LazyUpdate( const LazyUpdate& ); 96 // LazyUpdate& operator=( const LazyUpdate& ); 97 setInValue(input_type const & rIn)98 void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; } getInValue() const99 input_type const& getInValue() const { return m_aInput; } getOutValue() const100 output_type const& getOutValue() const { return this->implUpdateValue(m_aInput); } 101 operator *()102 input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; } operator ->()103 input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; } 104 operator *() const105 output_type const& operator*() const { return this->implUpdateValue(m_aInput); } operator ->() const106 output_type const* operator->() const { return &implUpdateValue(m_aInput); } 107 108 private: 109 input_type m_aInput; 110 }; 111 112 template< typename InputType, typename OutputType > struct DefaultFunctor 113 { 114 protected: 115 typedef OutputType output_type; 116 typedef InputType input_type; 117 DefaultFunctoro3tl::detail::DefaultFunctor118 DefaultFunctor() : 119 m_aOutput(), 120 m_bCacheDirty(true) 121 {} 122 implUpdateValueo3tl::detail::DefaultFunctor123 OutputType const& implUpdateValue( input_type const& rIn ) const 124 { 125 if( m_bCacheDirty ) 126 { 127 m_aOutput = output_type( rIn ); 128 m_bCacheDirty = false; 129 } 130 131 return m_aOutput; 132 } 133 134 mutable output_type m_aOutput; 135 mutable bool m_bCacheDirty; // when true, m_aOutput needs update 136 }; 137 138 template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer 139 { 140 protected: 141 typedef OutputType output_type; 142 typedef InputType input_type; 143 typedef FunctionType function_type; 144 FunctionPointero3tl::detail::FunctionPointer145 FunctionPointer() : 146 m_pFunc(), 147 m_aOutput(), 148 m_bCacheDirty(true) 149 150 {} 151 FunctionPointero3tl::detail::FunctionPointer152 explicit FunctionPointer( function_type const& pFunc ) : 153 m_pFunc(pFunc), 154 m_aOutput(), 155 m_bCacheDirty(true) 156 157 {} 158 implUpdateValueo3tl::detail::FunctionPointer159 output_type const& implUpdateValue( input_type const& rIn ) const 160 { 161 if( m_bCacheDirty ) 162 { 163 m_aOutput = m_pFunc( rIn ); 164 m_bCacheDirty = false; 165 } 166 167 return m_aOutput; 168 } 169 170 function_type m_pFunc; 171 mutable output_type m_aOutput; 172 mutable bool m_bCacheDirty; // when true, m_aOutput needs update 173 }; 174 } 175 176 // ----------------------------------------------------------------------------------------------------- 177 178 // partial specializations for the three LAZYUPDATE_* tags 179 180 template< typename InputType, typename OutputType > class LazyUpdate<InputType, 181 OutputType, 182 LAZYUPDATE_DIRECT_TAG> : 183 public detail::LazyUpdateImpl<InputType, 184 OutputType, 185 detail::DefaultFunctor<InputType, OutputType> > 186 { 187 public: LazyUpdate()188 LazyUpdate() {} LazyUpdate(InputType const & rIn)189 explicit LazyUpdate( InputType const& rIn ) : 190 detail::LazyUpdateImpl<InputType, 191 OutputType, 192 detail::DefaultFunctor<InputType, OutputType> >( 193 rIn, 194 detail::LazyUpdateImpl< 195 InputType, 196 OutputType, 197 detail::DefaultFunctor<InputType, OutputType> >::UNARY_CONSTRUCTOR_TAG ) 198 {} 199 }; 200 201 // ----------------------------------------------------------------------------------------------------- 202 203 template< typename InputType, typename OutputType > class LazyUpdate<InputType, 204 OutputType, 205 LAZYUPDATE_FUNCTION_TAG> : 206 public detail::LazyUpdateImpl<InputType, 207 OutputType, 208 detail::FunctionPointer< 209 InputType, 210 OutputType, 211 OutputType (*)( InputType const& ) > > 212 { 213 public: LazyUpdate(OutputType (* pFunc)(InputType const &))214 explicit LazyUpdate( OutputType (*pFunc)( InputType const& ) ) : 215 detail::LazyUpdateImpl<InputType, 216 OutputType, 217 detail::FunctionPointer< 218 InputType, 219 OutputType, 220 OutputType (*)( InputType const& )> >(pFunc) 221 {} LazyUpdate(OutputType (* pFunc)(InputType const &),InputType const & rIn)222 LazyUpdate( OutputType (*pFunc)( InputType const& ), 223 InputType const& rIn ) : 224 detail::LazyUpdateImpl<InputType, 225 OutputType, 226 detail::FunctionPointer< 227 InputType, 228 OutputType, 229 OutputType (*)( InputType const& )> >(pFunc,rIn) 230 {} 231 }; 232 233 // ----------------------------------------------------------------------------------------------------- 234 235 template< typename InputType, typename OutputType > class LazyUpdate<InputType, 236 OutputType, 237 LAZYUPDATE_FUNCTOR_TAG> : 238 public detail::LazyUpdateImpl<InputType, 239 OutputType, 240 detail::FunctionPointer< 241 InputType, 242 OutputType, 243 boost::function1<OutputType,InputType> > > 244 { 245 public: LazyUpdate(boost::function1<OutputType,InputType> const & rFunc)246 explicit LazyUpdate( boost::function1<OutputType,InputType> const& rFunc ) : 247 detail::LazyUpdateImpl<InputType, 248 OutputType, 249 detail::FunctionPointer< 250 InputType, 251 OutputType, 252 boost::function1<OutputType,InputType> > >(rFunc) 253 {} LazyUpdate(boost::function1<OutputType,InputType> const & rFunc,InputType const & rIn)254 LazyUpdate( boost::function1<OutputType,InputType> const& rFunc, 255 InputType const& rIn ) : 256 detail::LazyUpdateImpl<InputType, 257 OutputType, 258 detail::FunctionPointer< 259 InputType, 260 OutputType, 261 boost::function1<OutputType,InputType> > >(rFunc,rIn) 262 {} 263 }; 264 265 } 266 267 #endif /* INCLUDED_O3TL_LAZY_UPDATE_HXX */ 268