How to make Plain Actions from Static Member or Free Functions¶
Contents
- Use Case Variables:
- Function Namespace
Inside a namespace
In the global namespace
- Function location and linkage
In main program source
In a separate header/source file pair
Inside a static or shared library
- Function return type
returning a value
void return value
This just influences the way how the action created from it can be invoked.
Case 1 : Function in the main program source in global namespace¶
Example sourcecode in the repository is at /src/action_and_component_macros/case_1
- Needed Macros:
main.cpp: `HPX_PLAIN_ACTION <>`_.
This is the most simple case, but also limited. It would not work for a header file because it would create double definitions when included into several source files.
Example:
#include <hpx/hpx.hpp>
#include <hpx/hpx_main.hpp>
#include <iostream>
// Free function in GLOBAL namespace in main program
int compute_something(int data)
{
return data * 42;
}
HPX_PLAIN_ACTION(compute_something, compute_something_action);
int main(int argc, char* argv[])
{
std::cout << "Case 1:" << std::endl;
// template parameter: Action name
auto m_fut = hpx::async<compute_something_action>(hpx::find_here(), 42);
std::cout << "Result: " << m_fut.get() << std::endl;
return 0;
}
//example action invocation
auto my_future = HPX::async<compute_something_action>(some_locality_id, 371);
Case 2 : Function in the main program source in custom namespace¶
Example sourcecode in the repository is at /src/action_and_component_macros/case_2
- Needed Macros:
main.cpp: HPX_PLAIN_ACTION
This case works almost the same as case 1. You just have to apply the fully qualified function name to the macro instead. The namespace does NOT appear on the action, because it was defined and registered in the global namespace.
Example:
//main program
#include <hpx/hpx.hpp>
#include <hpx/hpx_main.hpp>
#include <iostream>
// Free function in CUSTOM namespace in main program
namespace application {
int compute_something( int data ) {
return data * 42;
}
}; // namespace application
HPX_PLAIN_ACTION( application::compute_something, compute_something_action );
int main( int argc, char* argv[] ) {
std::cout << "Case 2:" << std::endl;
// template parameter: Action name (still without namespace qualifier!)
auto m_fut = hpx::async<compute_something_action>( hpx::find_here( ), 42 );
std::cout << "Result: " << m_fut.get( ) << std::endl;
return 0;
}
//example action invocation
// template parameter: Action name
auto my_future = HPX::async<compute_something_action>(some_node_locality_id, 371);
Case 3 : Function in main program in custom namespace in separate header/source file pair¶
Example sourcecode in the repository is at /src/action_and_component_macros/case_3
- Needed Macros:
- header file: HPX_DEFINE_PLAIN_ACTION, HPX_REGISTER_ACTION_DECLARATIONsource file: HPX_REGISTER_ACTION
Explanation:
Now it gets slightly more complex. The Action is defined inside the namespace and thus invoking it requires using the namespace qualifier on it. Definition and registration are now split into two macros and the registration is declared in the header file, while the registration itself happens in the source file. This construction allows using the headerfile in multiple sources without generating duplicate symbol errors at link time.
// actions.hpp
#pragma once
#include <hpx/hpx.hpp>
namespace test {
// Free function in namespace
int some_function( );
// Define the action (inside the namespace):
// Parameters: function name, desired action name
HPX_DEFINE_PLAIN_ACTION( some_function, some_function_action );
}; // namespace test
// Declare the Registering of the Action (in global namespace)
// Parameters: Fully qualified action name, desired action name for serialization
// Note: When invoking the action we will still need the fully qualified action name!
HPX_REGISTER_ACTION_DECLARATION( test::some_function_action, some_function_action_serialized );
// actions.cpp
#include <hpx/hpx.hpp>
#include "actions.hpp"
namespace test {
// Free function in namespace
int some_function( ) {
return 42;
}
} // namespace test
// (outside namespace)
// Parameters: Fully qualified action name, action name for serialization
HPX_REGISTER_ACTION( test::some_function_action, some_function_action_serialized );
// main.cpp
#include <hpx/hpx.hpp>
#include <hpx/hpx_main.hpp>
#include "actions.hpp"
#include <iostream>
int main( ) {
std::cout << "Case 3:" << std::endl;
// template parameter: Fully qualified action name
auto m_fut = hpx::async<test::some_function_action>( hpx::find_here( ) );
std::cout << "Result: " << m_fut.get( ) << std::endl;
return 0;
}