Line | % of fetches | Source |
---|---|---|
1 | // Copyright (c) 2007-2015 Hartmut Kaiser | |
2 | // Copyright (c) 2011 Bryce Lelbach | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | /// \file hpx/runtime/components/component_factory.hpp | |
8 | ||
9 | #ifndef HPX_RUNTIME_COMPONENTS_COMPONENT_FACTORY_HPP | |
10 | #define HPX_RUNTIME_COMPONENTS_COMPONENT_FACTORY_HPP | |
11 | ||
12 | #ifdef DOXYGEN | |
13 | /// \def HPX_REGISTER_COMPONENT(type, name, mode) | |
14 | /// | |
15 | /// \brief Define a component factory for a component type | |
16 | /// | |
17 | /// This macro is used create and to register a minimal component factory for | |
18 | /// a component type which allows it to be remotely created using the | |
19 | /// \a hpx::new_<> function. | |
20 | /// | |
21 | /// This macro can be invoked with one, two or three arguments | |
22 | /// | |
23 | /// \param type The \a type parameter is a (fully decorated) type of the | |
24 | /// component type for which a factory should be defined. | |
25 | /// | |
26 | /// \param name The \a name parameter specifies the name to use to register | |
27 | /// the factory. This should uniquely (system-wide) identify the | |
28 | /// component type. The \a name parameter must conform to the C++ | |
29 | /// identifier rules (without any namespace). | |
30 | /// If this parameter is not given, the first parameter is used. | |
31 | /// | |
32 | /// \param mode The \a mode parameter has to be one of the defined enumeration | |
33 | /// values of the enumeration \a hpx::components::factory_state_enum. | |
34 | /// The default for this parameter is | |
35 | /// \a hpx::components::factory_enabled. | |
36 | /// | |
37 | #define HPX_REGISTER_COMPONENT(type, name, mode) | |
38 | ||
39 | #else | |
40 | ||
41 | #include <hpx/config.hpp> | |
42 | #include <hpx/runtime/components/component_factory_base.hpp> | |
43 | #include <hpx/runtime/components/component_registry.hpp> | |
44 | #include <hpx/runtime/components/component_type.hpp> | |
45 | #include <hpx/runtime/components/server/create_component.hpp> | |
46 | #include <hpx/runtime/components/server/destroy_component.hpp> | |
47 | #include <hpx/runtime/components/unique_component_name.hpp> | |
48 | #include <hpx/runtime/naming/address.hpp> | |
49 | #include <hpx/runtime/naming/name.hpp> | |
50 | #include <hpx/runtime/naming/resolver_client.hpp> | |
51 | #include <hpx/throw_exception.hpp> | |
52 | #include <hpx/util/atomic_count.hpp> | |
53 | #include <hpx/util/detail/count_num_args.hpp> | |
54 | #include <hpx/util/ini.hpp> | |
55 | #include <hpx/util/unique_function.hpp> | |
56 | ||
57 | #include <boost/preprocessor/cat.hpp> | |
58 | ||
59 | #include <cstddef> | |
60 | #include <string> | |
61 | ||
62 | /////////////////////////////////////////////////////////////////////////////// | |
63 | namespace hpx { namespace components | |
64 | { | |
65 | /////////////////////////////////////////////////////////////////////////// | |
66 | /// The \a component_factory provides a minimal implementation of a | |
67 | /// component's factory. If no additional functionality is required this | |
68 | /// type can be used to implement the full set of minimally required | |
69 | /// functions to be exposed by a component's factory instance. | |
70 | /// | |
71 | /// \tparam Component The component type this factory should be | |
72 | /// responsible for. | |
73 | template <typename Component> | |
74 | struct component_factory : public component_factory_base | |
75 | { | |
76 | /// \brief Construct a new factory instance | |
77 | /// | |
78 | /// \param global [in] The pointer to a \a hpx#util#section instance | |
79 | /// referencing the settings read from the [settings] | |
80 | /// section of the global configuration file (hpx.ini) | |
81 | /// This pointer may be nullptr if no such section has | |
82 | /// been found. | |
83 | /// \param local [in] The pointer to a \a hpx#util#section instance | |
84 | /// referencing the settings read from the section | |
85 | /// describing this component type: | |
86 | /// [hpx.components.\<name\>], where \<name\> is the | |
87 | /// instance name of the component as given in the | |
88 | /// configuration files. | |
89 | /// | |
90 | /// \note The contents of both sections has to be cloned in order to | |
91 | /// save the configuration setting for later use. | |
92 | component_factory(util::section const* global, | |
93 | util::section const* local, bool isenabled) | |
94 | : isenabled_(isenabled), refcnt_(0) | |
95 | { | |
96 | // store the configuration settings | |
97 | if (nullptr != global) | |
98 | global_settings_ = *global; | |
99 | if (nullptr != local) | |
100 | local_settings_ = *local; | |
101 | } | |
102 | ||
103 | /// Destruct a \a component_factory instance | |
104 | ~component_factory() {} | |
105 | ||
106 | /// \brief Return the unique identifier of the component type this | |
107 | /// factory is responsible for | |
108 | /// | |
109 | /// \param locality [in] The id of the locality this factory | |
110 | /// is responsible for. | |
111 | /// \param agas_client [in] The AGAS client to use for component id | |
112 | /// registration (if needed). | |
113 | /// | |
114 | /// \return Returns the unique identifier of the component type this | |
115 | /// factory instance is responsible for. This function throws | |
116 | /// on any error. | |
117 | component_type get_component_type(naming::gid_type const& locality, | |
118 | naming::resolver_client& agas_client) | |
119 | { | |
120 | typedef typename Component::type_holder type_holder; | |
121 | if (component_invalid == components::get_component_type<type_holder>()) | |
122 | { | |
123 | // First call to get_component_type, ask AGAS for a unique id. | |
124 | if (isenabled_) { | |
125 | component_type const ctype = | |
126 | agas_client.register_factory(locality, get_component_name()); | |
127 | ||
128 | if (component_invalid == ctype) { | |
129 | HPX_THROW_EXCEPTION(duplicate_component_id, | |
130 | "component_factory::get_component_type", | |
131 | "the component name " + get_component_name() + | |
132 | " is already in use"); | |
133 | } | |
134 | components::set_component_type<type_holder>(ctype); | |
135 | } | |
136 | else { | |
137 | component_type const ctype = | |
138 | agas_client.get_component_id(get_component_name()); | |
139 | ||
140 | components::set_component_type<type_holder>(ctype); | |
141 | } | |
142 | } | |
143 | return components::get_component_type<type_holder>(); | |
144 | } | |
145 | ||
146 | /// \brief Return the name of the component type this factory is | |
147 | /// responsible for | |
148 | /// | |
149 | /// \return Returns the name of the component type this factory | |
150 | /// instance is responsible for. This function throws on any | |
151 | /// error. | |
152 | std::string get_component_name() const | |
153 | { | |
154 | return unique_component_name<component_factory>::call(); | |
155 | } | |
156 | ||
157 | /// \brief Create one or more new component instances. | |
158 | /// | |
159 | /// \param count [in] The number of component instances to | |
160 | /// create. The value of this parameter should not | |
161 | /// be zero. | |
162 | /// | |
163 | /// \return Returns the GID of the first newly created component | |
164 | /// instance. If more than one component instance has been | |
165 | /// created (\a count > 1) the GID's of all new instances are | |
166 | /// sequential in a row. | |
167 | naming::gid_type create(std::size_t count = 1) | |
168 | { | |
169 | if (isenabled_) | |
170 | { | |
171 | naming::gid_type id = server::create<Component>(count); | |
172 | if (id) | |
173 | ++refcnt_; | |
174 | return id; | |
175 | } | |
176 | ||
177 | HPX_THROW_EXCEPTION(bad_request, | |
178 | "component_factory::create", | |
179 | "this factory instance is disabled for this locality (" + | |
180 | get_component_name() + ")"); | |
181 | return naming::invalid_gid; | |
182 | } | |
183 | ||
184 | /// \brief Create one new component instance and initialize it using | |
185 | /// the using the given constructor function. | |
186 | /// | |
187 | /// \param ctor [in] The constructor function to call in order to | |
188 | /// initialize the newly allocated object. | |
189 | /// | |
190 | /// \return Returns the GID of the first newly created component | |
191 | /// instance. | |
192 | naming::gid_type create_with_args( | |
193 | util::unique_function_nonser<void(void*)> const& ctor) | |
194 | { | |
195 | if (isenabled_) | |
196 | { | |
197 | naming::gid_type id = server::create<Component>(ctor); | |
198 | if (id) | |
199 | ++refcnt_; | |
200 | return id; | |
201 | } | |
202 | ||
203 | HPX_THROW_EXCEPTION(bad_request, | |
204 | "component_factory::create_with_args", | |
205 | "this factory instance is disabled for this locality (" + | |
206 | get_component_name() + ")"); | |
207 | return naming::invalid_gid; | |
208 | } | |
209 | ||
210 | /// \brief Create one new component instance and initialize it using | |
211 | /// the using the given constructor function. Assign the give | |
212 | /// GID to the new object. | |
213 | /// | |
214 | /// \param assign_gid [in] The GID to assign to the newly created object. | |
215 | /// \param ctor [in] The constructor function to call in order to | |
216 | /// initialize the newly allocated object. | |
217 | /// | |
218 | /// \return Returns the GID of the first newly created component | |
219 | /// instance (this is the same as assign_gid, if successful). | |
220 | naming::gid_type create_with_args( | |
221 | naming::gid_type const& assign_gid, | |
222 | util::unique_function_nonser<void(void*)> const& ctor) | |
223 | { | |
224 | if (isenabled_) | |
225 | { | |
226 | naming::gid_type id = | |
227 | server::create<Component>(assign_gid, ctor); | |
228 | if (id) | |
229 | ++refcnt_; | |
230 | return id; | |
231 | } | |
232 | ||
233 | HPX_THROW_EXCEPTION(bad_request, | |
234 | "component_factory::create_with_args", | |
235 | "this factory instance is disabled for this locality (" + | |
236 | get_component_name() + ")"); | |
237 | return naming::invalid_gid; | |
238 | } | |
239 | ||
240 | /// \brief Destroy one or more component instances | |
241 | /// | |
242 | /// \param gid [in] The gid of the first component instance to | |
243 | /// destroy. | |
244 | /// \param addr [in] The resolved address of the first component | |
245 | /// instance to destroy. | |
246 | void destroy(naming::gid_type const& gid, | |
247 | naming::address const& addr) | |
248 | { | |
249 | server::destroy<Component>(gid, addr); | |
250 | --refcnt_; | |
251 | } | |
252 | ||
253 | /// \brief Ask how many instances are alive of the type this factory is | |
254 | /// responsible for | |
255 | /// | |
256 | /// \return Returns the number of instances of the managed object type | |
257 | /// which are currently alive. | |
258 | long instance_count() const | |
259 | { | |
260 | return refcnt_; | |
261 | } | |
262 | ||
263 | #if defined(HPX_HAVE_SECURITY) | |
264 | /// \brief Return the required capabilities necessary to create an | |
265 | /// instance of a component using this factory instance. | |
266 | /// | |
267 | /// \return Returns required capabilities necessary to create a new | |
268 | /// instance of a component using this factory instance. | |
269 | virtual components::security::capability | |
270 | get_required_capabilities() const | |
271 | { | |
272 | using namespace components::security; | |
273 | return Component::get_required_capabilities( | |
274 | traits::capability<>::capability_create_component); | |
275 | } | |
276 | #endif | |
277 | ||
278 | protected: | |
279 | util::section global_settings_; | |
280 | util::section local_settings_; | |
281 | bool isenabled_; | |
282 | ||
283 | // count outstanding instances to avoid premature unloading | |
284 | util::atomic_count refcnt_; | |
285 | }; | |
286 | }} | |
287 | ||
288 | /////////////////////////////////////////////////////////////////////////////// | |
289 | // This macro is used create and to register a minimal component factory with | |
290 | // Hpx.Plugin. | |
291 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY(...) \ | |
292 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_(__VA_ARGS__) \ | |
293 | /**/ | |
294 | ||
295 | #define HPX_REGISTER_COMPONENT(...) \ | |
296 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_(__VA_ARGS__) \ | |
297 | /**/ | |
298 | ||
299 | #define HPX_REGISTER_ENABLED_COMPONENT_FACTORY(ComponentType, componentname) \ | |
300 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_3( \ | |
301 | ComponentType, componentname, ::hpx::components::factory_enabled) \ | |
302 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
303 | /**/ | |
304 | ||
305 | #define HPX_REGISTER_DISABLED_COMPONENT_FACTORY(ComponentType, componentname) \ | |
306 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_3( \ | |
307 | ComponentType, componentname, ::hpx::components::factory_disabled)\ | |
308 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
309 | /**/ | |
310 | ||
311 | /////////////////////////////////////////////////////////////////////////////// | |
312 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_(...) \ | |
313 | HPX_UTIL_EXPAND_(BOOST_PP_CAT( \ | |
314 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_, HPX_UTIL_PP_NARG(__VA_ARGS__)\ | |
315 | )(__VA_ARGS__)) \ | |
316 | /**/ | |
317 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_1(ComponentType) \ | |
318 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_3( \ | |
319 | ComponentType, ComponentType, ::hpx::components::factory_check) \ | |
320 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
321 | /**/ | |
322 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_2(ComponentType, componentname)\ | |
323 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_3( \ | |
324 | ComponentType, componentname, ::hpx::components::factory_check) \ | |
325 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
326 | /**/ | |
327 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_3( \ | |
328 | ComponentType, componentname, state) \ | |
329 | HPX_REGISTER_COMPONENT_FACTORY( \ | |
330 | hpx::components::component_factory<ComponentType>, componentname) \ | |
331 | HPX_DEF_UNIQUE_COMPONENT_NAME( \ | |
332 | hpx::components::component_factory<ComponentType>, componentname) \ | |
333 | template struct hpx::components::component_factory<ComponentType>; \ | |
334 | HPX_REGISTER_MINIMAL_COMPONENT_REGISTRY_3( \ | |
335 | ComponentType, componentname, state) \ | |
336 | /**/ | |
337 | ||
338 | /////////////////////////////////////////////////////////////////////////////// | |
339 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC(...) \ | |
340 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_(__VA_ARGS__) \ | |
341 | /**/ | |
342 | ||
343 | // same as above, just a better name | |
344 | ||
345 | /// This macro is used create and to register a minimal component factory for | |
346 | /// a component type which allows it to be remotely created using the | |
347 | /// hpx::new_<> function. | |
348 | /// This macro can be invoked with one, two or three arguments | |
349 | #define HPX_REGISTER_COMPONENT_DYNAMIC(...) \ | |
350 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_(__VA_ARGS__) \ | |
351 | /**/ | |
352 | ||
353 | #define HPX_REGISTER_ENABLED_COMPONENT_FACTORY_DYNAMIC(ComponentType, \ | |
354 | componentname) \ | |
355 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_3( \ | |
356 | ComponentType, componentname, ::hpx::components::factory_enabled) \ | |
357 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
358 | /**/ | |
359 | ||
360 | #define HPX_REGISTER_DISABLED_COMPONENT_FACTORY_DYNAMIC(ComponentType, \ | |
361 | componentname) \ | |
362 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_3( \ | |
363 | ComponentType, componentname, ::hpx::components::factory_disabled)\ | |
364 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
365 | /**/ | |
366 | ||
367 | ||
368 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_(...) \ | |
369 | HPX_UTIL_EXPAND_(BOOST_PP_CAT( \ | |
370 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_, \ | |
371 | HPX_UTIL_PP_NARG(__VA_ARGS__) \ | |
372 | )(__VA_ARGS__)) \ | |
373 | /**/ | |
374 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_1(ComponentType) \ | |
375 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_3( \ | |
376 | ComponentType, ComponentType, ::hpx::components::factory_check) \ | |
377 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
378 | /**/ | |
379 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_2(ComponentType, \ | |
380 | componentname) \ | |
381 | HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_3( \ | |
382 | ComponentType, componentname, ::hpx::components::factory_check) \ | |
383 | HPX_DEFINE_GET_COMPONENT_TYPE(ComponentType::wrapped_type) \ | |
384 | /**/ | |
385 | #define HPX_REGISTER_MINIMAL_COMPONENT_FACTORY_DYNAMIC_3( \ | |
386 | ComponentType, componentname, state) \ | |
387 | HPX_REGISTER_COMPONENT_FACTORY_DYNAMIC( \ | |
388 | hpx::components::component_factory<ComponentType>, componentname) \ | |
389 | HPX_DEF_UNIQUE_COMPONENT_NAME( \ | |
390 | hpx::components::component_factory<ComponentType>, componentname) \ | |
391 | template struct hpx::components::component_factory<ComponentType>; \ | |
392 | HPX_REGISTER_MINIMAL_COMPONENT_REGISTRY_DYNAMIC_3( \ | |
393 | ComponentType, componentname, state) \ | |
394 | /**/ | |
395 | ||
396 | #endif | |
397 | ||
398 | #endif /*HPX_RUNTIME_COMPONENTS_COMPONENT_FACTORY_HPP*/ | |
399 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.