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. Useful 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 : namespace detail
60 : {
61 : /// @internal
62 0 : template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor
63 : {
64 : public:
65 : typedef OutputType output_type;
66 : typedef InputType input_type;
67 :
68 : LazyUpdateImpl() :
69 : m_aInput()
70 : {}
71 :
72 0 : template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) :
73 : Functor(rParm),
74 0 : m_aInput()
75 0 : {}
76 :
77 : enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG };
78 : LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) :
79 : m_aInput(rInput)
80 : {}
81 :
82 : template< typename ParamType > LazyUpdateImpl( ParamType const& rParm,
83 : const input_type& rInput ) :
84 : Functor(rParm),
85 : m_aInput(rInput)
86 : {}
87 :
88 : // default copy ctor/assignment operator are ok
89 : // LazyUpdate( const LazyUpdate& );
90 : // LazyUpdate& operator=( const LazyUpdate& );
91 :
92 : void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; }
93 0 : input_type const& getInValue() const { return m_aInput; }
94 0 : output_type const& getOutValue() const { return this->implUpdateValue(m_aInput); }
95 :
96 0 : input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; }
97 0 : input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; }
98 :
99 0 : output_type const& operator*() const { return this->implUpdateValue(m_aInput); }
100 : output_type const* operator->() const { return &(this->implUpdateValue(m_aInput)); }
101 :
102 : private:
103 : input_type m_aInput;
104 : };
105 :
106 : template< typename InputType, typename OutputType > struct DefaultFunctor
107 : {
108 : protected:
109 : typedef OutputType output_type;
110 : typedef InputType input_type;
111 :
112 : DefaultFunctor() :
113 : m_aOutput(),
114 : m_bCacheDirty(true)
115 : {}
116 :
117 : OutputType const& implUpdateValue( input_type const& rIn ) const
118 : {
119 : if( m_bCacheDirty )
120 : {
121 : m_aOutput = output_type( rIn );
122 : m_bCacheDirty = false;
123 : }
124 :
125 : return m_aOutput;
126 : }
127 :
128 : mutable output_type m_aOutput;
129 : mutable bool m_bCacheDirty; // when true, m_aOutput needs update
130 : };
131 :
132 0 : template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer
133 : {
134 : protected:
135 : typedef OutputType output_type;
136 : typedef InputType input_type;
137 : typedef FunctionType function_type;
138 :
139 : FunctionPointer() :
140 : m_pFunc(),
141 : m_aOutput(),
142 : m_bCacheDirty(true)
143 :
144 : {}
145 :
146 0 : explicit FunctionPointer( function_type const& pFunc ) :
147 : m_pFunc(pFunc),
148 : m_aOutput(),
149 0 : m_bCacheDirty(true)
150 :
151 0 : {}
152 :
153 0 : output_type const& implUpdateValue( input_type const& rIn ) const
154 : {
155 0 : if( m_bCacheDirty )
156 : {
157 0 : m_aOutput = m_pFunc( rIn );
158 0 : m_bCacheDirty = false;
159 : }
160 :
161 0 : return m_aOutput;
162 : }
163 :
164 : function_type m_pFunc;
165 : mutable output_type m_aOutput;
166 : mutable bool m_bCacheDirty; // when true, m_aOutput needs update
167 : };
168 : }
169 :
170 : // partial specializations for the three LAZYUPDATE_* tags
171 : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
172 : OutputType,
173 : LAZYUPDATE_DIRECT_TAG> :
174 : public detail::LazyUpdateImpl<InputType,
175 : OutputType,
176 : detail::DefaultFunctor<InputType, OutputType> >
177 : {
178 : public:
179 : LazyUpdate() {}
180 : explicit LazyUpdate( InputType const& rIn ) :
181 : detail::LazyUpdateImpl<InputType,
182 : OutputType,
183 : detail::DefaultFunctor<InputType, OutputType> >(
184 : rIn,
185 : detail::LazyUpdateImpl<
186 : InputType,
187 : OutputType,
188 : detail::DefaultFunctor<InputType, OutputType> >::UNARY_CONSTRUCTOR_TAG )
189 : {}
190 : };
191 :
192 0 : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
193 : OutputType,
194 : LAZYUPDATE_FUNCTION_TAG> :
195 : public detail::LazyUpdateImpl<InputType,
196 : OutputType,
197 : detail::FunctionPointer<
198 : InputType,
199 : OutputType,
200 : OutputType (*)( InputType const& ) > >
201 : {
202 : public:
203 0 : explicit LazyUpdate( OutputType (*pFunc)( InputType const& ) ) :
204 : detail::LazyUpdateImpl<InputType,
205 : OutputType,
206 : detail::FunctionPointer<
207 : InputType,
208 : OutputType,
209 0 : OutputType (*)( InputType const& )> >(pFunc)
210 0 : {}
211 : LazyUpdate( OutputType (*pFunc)( InputType const& ),
212 : InputType const& rIn ) :
213 : detail::LazyUpdateImpl<InputType,
214 : OutputType,
215 : detail::FunctionPointer<
216 : InputType,
217 : OutputType,
218 : OutputType (*)( InputType const& )> >(pFunc,rIn)
219 : {}
220 : };
221 :
222 0 : template< typename InputType, typename OutputType > class LazyUpdate<InputType,
223 : OutputType,
224 : LAZYUPDATE_FUNCTOR_TAG> :
225 : public detail::LazyUpdateImpl<InputType,
226 : OutputType,
227 : detail::FunctionPointer<
228 : InputType,
229 : OutputType,
230 : boost::function1<OutputType,InputType> > >
231 : {
232 : public:
233 0 : explicit LazyUpdate( boost::function1<OutputType,InputType> const& rFunc ) :
234 : detail::LazyUpdateImpl<InputType,
235 : OutputType,
236 : detail::FunctionPointer<
237 : InputType,
238 : OutputType,
239 0 : boost::function1<OutputType,InputType> > >(rFunc)
240 0 : {}
241 : LazyUpdate( boost::function1<OutputType,InputType> const& rFunc,
242 : InputType const& rIn ) :
243 : detail::LazyUpdateImpl<InputType,
244 : OutputType,
245 : detail::FunctionPointer<
246 : InputType,
247 : OutputType,
248 : boost::function1<OutputType,InputType> > >(rFunc,rIn)
249 : {}
250 : };
251 :
252 : }
253 :
254 : #endif
255 :
256 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|