Actions are special types we use to describe possibly remote operations.
For every global function and every member function which has to be invoked
distantly, a special type must be defined. For any global function the
special macro HPX_PLAIN_ACTION
can be used to define the action type. Here is an example demonstrating
this:
namespace app
{
void some_global_function(double d)
{
cout << d;
}
}
// This will define the action type 'some_global_action' which represents
// the function 'app::some_global_function'.
HPX_PLAIN_ACTION
(app::some_global_function, some_global_action);
Important | |
---|---|
The macro |
If the action type should be defined somewhere not in global namespace,
the action type definition has to be split into two macro invocations (HPX_DEFINE_PLAIN_ACTION
and HPX_REGISTER_PLAIN_ACTION
)
as shown in the next example:
namespace app { void some_global_function(double d) { cout << d; } // On conforming compilers the following macro expands to: // // typedef hpx::actions::make_action< // decltype(&some_global_function), &some_global_function // >::type some_global_action; // // This will define the action type 'some_global_action' which represents // the function 'some_global_function'.HPX_DEFINE_PLAIN_ACTION
(some_global_function, some_global_action); } // The following macro expands to a series of definitions of global objects // which are needed for proper serialization and initialization support // enabling the remote invocation of the function `some_global_function`.HPX_REGISTER_PLAIN_ACTION
(app::some_global_action);
The shown code defines an action type some_global_action
inside the namespace app
.
Important | |
---|---|
If the action type definition is split between two macros as shown above,
the name of the action type to create has to be the same for both macro
invocations (here |
For member functions of objects which have been registered with AGAS (e.g.
'components') a different registration macro HPX_DEFINE_COMPONENT_ACTION
has to be utilized. Any component needs to be declared in a header file
and have some special support macros defined in a source file. Here is
an example demonstrating this. The first snippet has to go into the header
file:
namespace app { struct some_component : hpx::components::simple_component_base<some_component> { int some_member_function(std::string s) { return boost::lexical_cast<int>(s); } // This will define the action type 'some_member_action' which // represents the member function 'some_member_function' of the // obect type 'some_component'.HPX_DEFINE_COMPONENT_ACTION
(some_component, some_member_function, some_member_action); }; } // Note: The second arguments to the macro below have to be systemwide-unique // C++ identifiersHPX_REGISTER_ACTION_DECLARATION
(app::some_component::some_member_action , some_component_some_action );
The next snippet belongs to the source file (e.g. the main application in the most simple case:
typedef hpx::components::simple_component< app::some_component > component_type; typedef app::some_component some_component; HPX_REGISTER_MINIMAL_COMPONENT_FACTORY( component_type, some_component ); // The parameters for this macro have to be the same as used in the corresponding // HPX_REGISTER_ACTION_DECLARATION() macro invocation above typedef some_component::some_member_action some_component_some_action; HPX_REGISTER_ACTION( some_component_some_action );
Granted, these macro invocations are a bit more complex than for simple global functions, however we believe they are still manageable.
The most important macro invocation is the HPX_DEFINE_COMPONENT_ACTION
in the header file as this defines the action type we need to invoke the
member function. For a complete example of a simple component action see
component_in_executable.cpp