| 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.