Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Authors: Sebastian Reiter, Andreas Vogel
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG_BRIDGE__GLOBAL_FUNCTION__
34 : #define __H__UG_BRIDGE__GLOBAL_FUNCTION__
35 :
36 : #include <string>
37 : #include <vector>
38 : #include <sstream>
39 : #include "parameter_stack.h"
40 : #include "function_traits.h"
41 : #include "param_to_type_value_list.h"
42 : #include "common/ug_config.h"
43 : #include <iostream>
44 :
45 : #ifdef PROFILE_BRIDGE
46 : #ifndef UG_PROFILER
47 : #error "You need to define UG_PROFILER to use PROFILE_BRIDGE"
48 : #endif
49 : #include "common/profiler/runtime_profile_info.h"
50 :
51 : #endif
52 :
53 : namespace ug
54 : {
55 : namespace bridge
56 : {
57 :
58 : /// \addtogroup registry
59 : /// \{
60 :
61 : /// Exception throw, if method name has not been given
62 : struct UG_REGISTRY_ERROR_FunctionOrMethodNameMissing {};
63 :
64 : /// Base class for function/method export
65 : class UG_API ExportedFunctionBase
66 : {
67 : public:
68 : ExportedFunctionBase(const std::string& funcName, const std::string& funcOptions,
69 : const std::string& retValInfos, const std::string& paramInfos,
70 : const std::string& tooltip, const std::string& help);
71 :
72 : /// name of function
73 : const std::string& name() const {return m_name;}
74 :
75 : /// name of function
76 : const std::string& options() const {return m_methodOptions;}
77 :
78 : /// name of return value
79 : const std::string& return_name() const {return return_info(0);}
80 :
81 : /// type info of return type
82 : const std::string& return_info(size_t i) const {return m_vRetValInfo.at(i);}
83 :
84 : /// type info of return value
85 : const std::vector<std::string>& return_info_vec() const {return m_vRetValInfo;}
86 :
87 : /// number of parameters.
88 : size_t num_parameter() const {return m_vvParamInfo.size();}
89 :
90 : /// number of info strings for one parameter
91 : size_t num_infos(size_t i) const {return m_vvParamInfo.at(i).size();}
92 :
93 : /// class name of parameter i
94 : const char* parameter_class_name(size_t i) const {return params_in().class_name((int)i);}
95 :
96 : /// name of parameter i
97 0 : const std::string& parameter_name(size_t i) const {return parameter_info(i, 0);}
98 :
99 : /// type info of all parameters
100 0 : const std::string& parameter_info(size_t i, size_t j) const {return m_vvParamInfo.at(i).at(j);}
101 :
102 : /// type info of i th parameters
103 : const std::vector<std::string>& parameter_info_vec(size_t i) const {return m_vvParamInfo.at(i);}
104 :
105 : /// whole string of all type infos for of all parameters
106 : const std::string& parameter_info_string() const {return m_paramInfos;}
107 :
108 : /// gives some information to the exported functions
109 : const std::string& tooltip() const {return m_tooltip;}
110 :
111 : /// help informations
112 : const std::string& help() const {return m_help;}
113 :
114 : /// parameter list for input values
115 0 : const ParameterInfo& params_in() const {return m_paramsIn;}
116 :
117 : /// parameter list for input values
118 0 : const ParameterInfo& params_out() const {return m_paramsOut;}
119 :
120 : // todo: we export non-const here, since we can not make ExportedClass<TClass> a friend
121 : /// non-const export of param list
122 : ParameterInfo& params_in() {return m_paramsIn;}
123 :
124 : /// returns true if all parameters of the function are correctly declared
125 : bool check_consistency(std::string classname = "") const;
126 :
127 : protected:
128 : template <typename TFunc>
129 6017 : void create_parameter_stack()
130 : {
131 : ////////////////////////////////////////////////
132 : // Create parameter stack for PARAMETERS
133 : ////////////////////////////////////////////////
134 : typedef typename func_traits<TFunc>::params_type params_type;
135 1879 : CreateParameterInfo<params_type>::create(m_paramsIn);
136 :
137 : // arbitrary choosen minimum number of infos exported
138 : // (If values non given we set them to an empty string)
139 : const size_t MinNumInfos = 3; // for "name | style | options"
140 :
141 : // Fill missing Parameter
142 6017 : m_vvParamInfo.resize(m_paramsIn.size());
143 : // resize missing infos for each parameter
144 18149 : for(int i = 0; i < (int)m_vvParamInfo.size(); ++i)
145 41966 : for(size_t j = m_vvParamInfo.at(i).size(); j < MinNumInfos; ++j)
146 59668 : m_vvParamInfo.at(i).push_back(std::string(""));
147 :
148 : ////////////////////////////////////////////////
149 : // Create parameter stack for RETURN VALUES
150 : ////////////////////////////////////////////////
151 : typedef typename func_traits<TFunc>::return_type return_type;
152 : CreateParameterInfoOut<return_type>::create(m_paramsOut);
153 :
154 : // resize missing infos for return value
155 22694 : for(size_t j = m_vRetValInfo.size(); j < MinNumInfos; ++j)
156 33354 : m_vRetValInfo.push_back(std::string(""));
157 6017 : }
158 :
159 : // help function to tokenize the parameter string
160 : void tokenize(const std::string& str, std::vector<std::string>& tokens,
161 : const char delimiter);
162 :
163 : protected:
164 : std::string m_name;
165 : std::string m_methodOptions;
166 :
167 : std::string m_retValInfos; // string with Infos about return type
168 : std::vector<std::string> m_vRetValInfo; // tokenized Infos
169 :
170 : // string with Infos about parameter
171 : std::string m_paramInfos;
172 :
173 : // tokenized strings for each Parameter and each Info (name | #style | options | ...)
174 : std::vector<std::vector<std::string> > m_vvParamInfo;
175 :
176 : std::string m_tooltip;
177 : std::string m_help;
178 :
179 : ParameterInfo m_paramsIn;
180 : ParameterInfo m_paramsOut;
181 : };
182 :
183 :
184 : ///This class describes a wrapper for a c++ - function, that is exported by ug
185 1819 : class UG_API ExportedFunction : public ExportedFunctionBase
186 : {
187 : public:
188 : // all c++ functions are wrapped by a proxy function of the following type
189 : typedef void (*ProxyFunc)(void* func, const ParameterStack& in, ParameterStack& out);
190 :
191 : template <typename TFunc>
192 1819 : ExportedFunction( TFunc f, ProxyFunc pf,
193 : const std::string& name, const std::string& funcOptions,
194 : const std::string& group,
195 : const std::string& retValInfos, const std::string& paramInfos,
196 : const std::string& tooltip, const std::string& help)
197 : : ExportedFunctionBase(name, funcOptions, retValInfos,
198 : paramInfos, tooltip, help),
199 1819 : m_group(group), m_func((void*)f), m_proxy_func(pf)
200 : #ifdef PROFILE_BRIDGE
201 : ,m_dpi(ExportedFunctionBase::name().c_str(), true, "registry", false)
202 : #endif
203 : {
204 1819 : create_parameter_stack<TFunc>();
205 1819 : }
206 :
207 : /// executes the function
208 : void execute(const ParameterStack& paramsIn, ParameterStack& paramsOut) const
209 : {
210 : #ifdef PROFILE_BRIDGE
211 : m_dpi.beginNode();
212 : #endif
213 0 : m_proxy_func(m_func, paramsIn, paramsOut);
214 :
215 : #ifdef PROFILE_BRIDGE
216 : m_dpi.endNode();
217 : #endif
218 :
219 0 : }
220 :
221 : /// return groups
222 : const std::string& group() const {return m_group;}
223 :
224 : protected:
225 : /// save groups
226 : std::string m_group;
227 :
228 : /// pointer to to function
229 : void* m_func;
230 :
231 : /// proxy function
232 : ProxyFunc m_proxy_func;
233 :
234 : #ifdef PROFILE_BRIDGE
235 : mutable RuntimeProfileInfo m_dpi;
236 : #endif
237 : };
238 :
239 : ////////////////////////////////////////////////////////////////////////
240 : // ExportedFunctionGroup (sreiter)
241 : /// Groups of Functions - useful to realize overloaded functions
242 : class UG_API ExportedFunctionGroup
243 : {
244 : public:
245 : /// constructor
246 321 : ExportedFunctionGroup(const std::string& name) : m_name(name){}
247 :
248 : /// destructor
249 321 : ~ExportedFunctionGroup()
250 : {
251 2140 : for(size_t i = 0; i < m_overloads.size(); ++i)
252 3638 : delete m_overloads[i].m_func;
253 321 : }
254 :
255 : /// name of function group
256 405921 : const std::string& name() const {return m_name;}
257 :
258 : /// adds an overload. Returns false if the overload already existed.
259 : template <class TFunc>
260 : ExportedFunction*
261 1819 : add_overload ( TFunc f, ExportedFunction::ProxyFunc pf,
262 : const std::string& funcOptions, const std::string& group,
263 : const std::string& retValInfos, const std::string& paramInfos,
264 : const std::string& tooltip, const std::string& help)
265 : {
266 1819 : size_t typeID = GetUniqueTypeID<TFunc>();
267 :
268 : // make sure that the overload didn't exist
269 1819 : if(get_overload_by_type_id(typeID))return NULL;
270 :
271 : // create a new overload
272 1819 : ExportedFunction* func = new ExportedFunction(f, pf, m_name,
273 : funcOptions, group, retValInfos,
274 : paramInfos, tooltip, help);
275 :
276 3638 : m_overloads.push_back(Overload(func, typeID));
277 1819 : return func;
278 : }
279 :
280 : size_t num_overloads() const {return m_overloads.size();}
281 :
282 0 : ExportedFunction* get_overload(size_t index)
283 0 : {return m_overloads.at(index).m_func;}
284 :
285 0 : const ExportedFunction* get_overload(size_t index) const
286 0 : {return m_overloads.at(index).m_func;}
287 :
288 : template <class TType>
289 : ExportedFunction* get_overload_by_type()
290 : {
291 : size_t typeID = GetUniqueTypeID<TType>();
292 : return get_overload_by_type_id(typeID);
293 : }
294 :
295 : template <class TType>
296 : const ExportedFunction* get_overload_by_type() const
297 : {
298 : size_t typeID = GetUniqueTypeID<TType>();
299 : return get_overload_by_type_id(typeID);
300 : }
301 :
302 : ExportedFunction* get_overload_by_type_id(size_t typeID)
303 : {
304 50942 : for(size_t i = 0; i < m_overloads.size(); ++i){
305 49123 : if(m_overloads[i].m_typeID == typeID)
306 0 : return m_overloads[i].m_func;
307 : }
308 : return NULL;
309 : }
310 :
311 : const ExportedFunction* get_overload_by_type_id(size_t typeID) const
312 : {
313 : for(size_t i = 0; i < m_overloads.size(); ++i){
314 : if(m_overloads[i].m_typeID == typeID)
315 : return m_overloads[i].m_func;
316 : }
317 : return NULL;
318 : }
319 :
320 : size_t get_overload_type_id(size_t index) const
321 : {return m_overloads.at(index).m_typeID;}
322 :
323 : private:
324 : struct Overload{
325 : Overload() {}
326 1819 : Overload(ExportedFunction* func, size_t typeID) :
327 1819 : m_func(func), m_typeID(typeID) {}
328 : ExportedFunction* m_func;
329 : size_t m_typeID;
330 : };
331 :
332 : std::string m_name;
333 : std::vector<Overload> m_overloads;
334 : };
335 :
336 : /**
337 : * Function that forwards for function pointer for a signature
338 : */
339 : template <typename TFunc, typename TRet = typename func_traits<TFunc>::return_type>
340 : struct FunctionProxy
341 : {
342 0 : static void apply(void* func, const ParameterStack& in, ParameterStack& out)
343 : {
344 : typedef typename func_traits<TFunc>::params_type params_type;
345 0 : TFunc fp = (TFunc) func;
346 :
347 : // convert parameter stack
348 0 : ParameterStackToTypeValueList<params_type> args(in);
349 :
350 : // apply
351 0 : TRet res = func_traits<TFunc>::apply(fp, args);
352 :
353 : // write result
354 0 : out.push<TRet>(res);
355 0 : }
356 : };
357 :
358 : // specialization if no return value given
359 : template <typename TFunc>
360 : struct FunctionProxy<TFunc, void>
361 : {
362 0 : static void apply(void* func, const ParameterStack& in, ParameterStack& out)
363 : {
364 : typedef typename func_traits<TFunc>::params_type params_type;
365 0 : TFunc fp = (TFunc) func;
366 :
367 : // convert parameter stack
368 0 : ParameterStackToTypeValueList<params_type> args(in);
369 :
370 : // apply
371 0 : func_traits<TFunc>::apply(fp, args);
372 0 : }
373 : };
374 :
375 : // end group registry
376 : /// \}
377 :
378 : } // end namespace bridge
379 : } // end namespace ug
380 :
381 :
382 : #endif /* __H__UG_BRIDGE__GLOBAL_FUNCTION__ */
|