Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #ifndef INCLUDED_O3TL_LAZY_UPDATE_HXX
21 : : #define INCLUDED_O3TL_LAZY_UPDATE_HXX
22 : :
23 : : #include <sal/types.h>
24 : : #include <boost/function.hpp>
25 : :
26 : : namespace o3tl
27 : : {
28 : : /** Update output object lazily
29 : :
30 : : This template collects data in input type, and updates the
31 : : output type with the given update functor, but only if the
32 : : output is requested. Usefúl if updating is expensive, or input
33 : : changes frequently, but output is only comparatively seldom
34 : : used.
35 : :
36 : : @example
37 : : <pre>
38 : : LazyUpdate<InType,OutType,LAZYUPDATE_DIRECT_TAG> myValue;
39 : : *myValue = newInput;
40 : : myValue->updateInput( this, that, those );
41 : :
42 : : output( *myValue );
43 : : </pre>
44 : : or
45 : : <pre>
46 : : output( myValue.getOutValue() );
47 : : </pre>
48 : : if the compiler does not recognize the const context.
49 : : */
50 : : template< typename InputType, typename OutputType, typename Tag > class LazyUpdate;
51 : :
52 : : /// LazyUpdate specialization takes boost::function argument
53 : : struct LAZYUPDATE_FUNCTOR_TAG {};
54 : : /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument
55 : : struct LAZYUPDATE_FUNCTION_TAG {};
56 : : /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument
57 : : struct LAZYUPDATE_DIRECT_TAG {};
58 : :
59 : : // -----------------------------------------------------------------------------------------------------
60 : :
61 : : namespace detail
62 : : {
63 : : /// @internal
64 : 0 : template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor
65 : : {
66 : : public:
67 : : typedef OutputType output_type;
68 : : typedef InputType input_type;
69 : :
70 : : LazyUpdateImpl() :
71 : : m_aInput()
72 : : {}
73 : :
74 : 0 : template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) :
75 : : Functor(rParm),
76 : 0 : m_aInput()
77 : 0 : {}
78 : :
79 : : enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG };
80 : : LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) :
81 : : m_aInput(rInput)
82 : : {}
83 : :
84 : : template< typename ParamType > LazyUpdateImpl( ParamType const& rParm,
85 : : const input_type& rInput ) :
86 : : Functor(rParm),
87 : : m_aInput(rInput)
88 : : {}
89 : :
90 : : // default copy ctor/assignment operator are ok
91 : : // LazyUpdate( const LazyUpdate& );
92 : : // LazyUpdate& operator=( const LazyUpdate& );
93 : :
94 : : void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; }
95 : 0 : input_type const& getInValue() const { return m_aInput; }
96 : 0 : output_type const& getOutValue() const { return this->implUpdateValue(m_aInput); }
97 : :
98 : 0 : input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; }
99 : 0 : input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; }
100 : :
101 : 0 : output_type const& operator*() const { return this->implUpdateValue(m_aInput); }
102 : : output_type const* operator->() const { return &(this->implUpdateValue(m_aInput)); }
103 : :
104 : : private:
105 : : input_type m_aInput;
106 : : };
107 : :
108 : : template< typename InputType, typename OutputType > struct DefaultFunctor
109 : : {
110 : : protected:
111 : : typedef OutputType output_type;
112 : : typedef InputType input_type;
113 : :
114 : : DefaultFunctor() :
115 : : m_aOutput(),
116 : : m_bCacheDirty(true)
117 : : {}
118 : :
119 : : OutputType const& implUpdateValue( input_type const& rIn ) const
120 : : {
121 : : if( m_bCacheDirty )
122 : : {
123 : : m_aOutput = output_type( rIn );
124 : : m_bCacheDirty = false;
125 : : }
126 : :
127 : : return m_aOutput;
128 : : }
129 : :
130 : : mutable output_type m_aOutput;
131 : : mutable bool m_bCacheDirty; // when true, m_aOutput needs update
132 : : };
133 : :
134 : 0 : template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer
135 : : {
136 : : protected:
137 : : typedef OutputType output_type;
138 : : typedef InputType input_type;
139 : : typedef FunctionType function_type;
140 : :
141 : : FunctionPointer() :
142 : : m_pFunc(),
143 : : m_aOutput(),
144 : : m_bCacheDirty(true)
145 : :
146 : : {}
147 : :
148 : 0 : explicit FunctionPointer( function_type const& pFunc ) :
149 : : m_pFunc(pFunc),
150 : : m_aOutput(),
151 : 0 : m_bCacheDirty(true)
152 : :
153 : 0 : {}
154 : :
155 : 0 : output_type const& implUpdateValue( input_type const& rIn ) const
156 : : {
157 : 0 : if( m_bCacheDirty )
158 : : {
159 : 0 : m_aOutput = m_pFunc( rIn );
160 : 0 : m_bCacheDirty = false;
161 : : }
162 : :
163 : 0 : return m_aOutput;
164 : : }
165 : :
166 : : function_type m_pFunc;
167 : : mutable output_type m_aOutput;
168 : : mutable bool m_bCacheDirty; // when true, m_aOutput needs update
169 : : };
170 : : }
171 : :
172 : : // -----------------------------------------------------------------------------------------------------
173 : :
174 : : // partial specializations for the three LAZYUPDATE_* tags
175 : :
176 : : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
177 : : OutputType,
178 : : LAZYUPDATE_DIRECT_TAG> :
179 : : public detail::LazyUpdateImpl<InputType,
180 : : OutputType,
181 : : detail::DefaultFunctor<InputType, OutputType> >
182 : : {
183 : : public:
184 : : LazyUpdate() {}
185 : : explicit LazyUpdate( InputType const& rIn ) :
186 : : detail::LazyUpdateImpl<InputType,
187 : : OutputType,
188 : : detail::DefaultFunctor<InputType, OutputType> >(
189 : : rIn,
190 : : detail::LazyUpdateImpl<
191 : : InputType,
192 : : OutputType,
193 : : detail::DefaultFunctor<InputType, OutputType> >::UNARY_CONSTRUCTOR_TAG )
194 : : {}
195 : : };
196 : :
197 : : // -----------------------------------------------------------------------------------------------------
198 : :
199 : 0 : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
200 : : OutputType,
201 : : LAZYUPDATE_FUNCTION_TAG> :
202 : : public detail::LazyUpdateImpl<InputType,
203 : : OutputType,
204 : : detail::FunctionPointer<
205 : : InputType,
206 : : OutputType,
207 : : OutputType (*)( InputType const& ) > >
208 : : {
209 : : public:
210 : 0 : explicit LazyUpdate( OutputType (*pFunc)( InputType const& ) ) :
211 : : detail::LazyUpdateImpl<InputType,
212 : : OutputType,
213 : : detail::FunctionPointer<
214 : : InputType,
215 : : OutputType,
216 : 0 : OutputType (*)( InputType const& )> >(pFunc)
217 : 0 : {}
218 : : LazyUpdate( OutputType (*pFunc)( InputType const& ),
219 : : InputType const& rIn ) :
220 : : detail::LazyUpdateImpl<InputType,
221 : : OutputType,
222 : : detail::FunctionPointer<
223 : : InputType,
224 : : OutputType,
225 : : OutputType (*)( InputType const& )> >(pFunc,rIn)
226 : : {}
227 : : };
228 : :
229 : : // -----------------------------------------------------------------------------------------------------
230 : :
231 : 0 : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
232 : : OutputType,
233 : : LAZYUPDATE_FUNCTOR_TAG> :
234 : : public detail::LazyUpdateImpl<InputType,
235 : : OutputType,
236 : : detail::FunctionPointer<
237 : : InputType,
238 : : OutputType,
239 : : boost::function1<OutputType,InputType> > >
240 : : {
241 : : public:
242 : 0 : explicit LazyUpdate( boost::function1<OutputType,InputType> const& rFunc ) :
243 : : detail::LazyUpdateImpl<InputType,
244 : : OutputType,
245 : : detail::FunctionPointer<
246 : : InputType,
247 : : OutputType,
248 : 0 : boost::function1<OutputType,InputType> > >(rFunc)
249 : 0 : {}
250 : : LazyUpdate( boost::function1<OutputType,InputType> const& rFunc,
251 : : InputType const& rIn ) :
252 : : detail::LazyUpdateImpl<InputType,
253 : : OutputType,
254 : : detail::FunctionPointer<
255 : : InputType,
256 : : OutputType,
257 : : boost::function1<OutputType,InputType> > >(rFunc,rIn)
258 : : {}
259 : : };
260 : :
261 : : }
262 : :
263 : : #endif /* INCLUDED_O3TL_LAZY_UPDATE_HXX */
264 : :
265 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|