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: */
|