Skip to content

Commit 205bbcb

Browse files
authored
Merge pull request STEllAR-GROUP#6677 from STEllAR-GROUP/manage_runtime
Offer a runtime manager object
2 parents cbd2256 + 32a924d commit 205bbcb

File tree

9 files changed

+323
-166
lines changed

9 files changed

+323
-166
lines changed

examples/quickstart/init_globally.cpp

Lines changed: 43 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include <hpx/condition_variable.hpp>
2121
#include <hpx/functional.hpp>
22-
#include <hpx/init.hpp>
22+
#include <hpx/manage_runtime.hpp>
2323
#include <hpx/modules/runtime_local.hpp>
2424
#include <hpx/mutex.hpp>
2525
#include <hpx/thread.hpp>
@@ -66,109 +66,6 @@ char** __argv = *_NSGetArgv();
6666

6767
#endif
6868

69-
class manage_global_runtime_impl
70-
{
71-
public:
72-
manage_global_runtime_impl()
73-
: running_(false)
74-
, rts_(nullptr)
75-
{
76-
#if defined(HPX_WINDOWS)
77-
hpx::detail::init_winsocket();
78-
#endif
79-
80-
std::vector<std::string> const cfg = {
81-
// make sure hpx_main is always executed
82-
"hpx.run_hpx_main!=1",
83-
// allow for unknown command line options
84-
"hpx.commandline.allow_unknown!=1",
85-
// disable HPX' short options
86-
"hpx.commandline.aliasing!=0"};
87-
88-
using hpx::placeholders::_1;
89-
using hpx::placeholders::_2;
90-
hpx::function<int(int, char**)> start_function =
91-
hpx::bind(&manage_global_runtime_impl::hpx_main, this, _1, _2);
92-
hpx::init_params init_args;
93-
init_args.cfg = cfg;
94-
init_args.mode = hpx::runtime_mode::default_;
95-
96-
if (!hpx::start(start_function, __argc, __argv, init_args))
97-
{
98-
// Something went wrong while initializing the runtime.
99-
// This early we can't generate any output, just bail out.
100-
std::abort();
101-
}
102-
103-
// Wait for the main HPX thread (hpx_main below) to have started running
104-
std::unique_lock<std::mutex> lk(startup_mtx_);
105-
while (!running_)
106-
startup_cond_.wait(lk);
107-
}
108-
109-
~manage_global_runtime_impl()
110-
{
111-
// notify hpx_main above to tear down the runtime
112-
{
113-
std::lock_guard<hpx::spinlock> lk(mtx_);
114-
rts_ = nullptr; // reset pointer
115-
}
116-
117-
cond_.notify_one(); // signal exit
118-
119-
// wait for the runtime to exit
120-
hpx::stop();
121-
}
122-
123-
// registration of external (to HPX) threads
124-
void register_thread(char const* name)
125-
{
126-
hpx::register_thread(rts_, name);
127-
}
128-
void unregister_thread()
129-
{
130-
hpx::unregister_thread(rts_);
131-
}
132-
133-
protected:
134-
// Main HPX thread, does nothing but wait for the application to exit
135-
int hpx_main(int, char*[])
136-
{
137-
// Store a pointer to the runtime here.
138-
rts_ = hpx::get_runtime_ptr();
139-
140-
// Signal to constructor that thread has started running.
141-
{
142-
std::lock_guard<std::mutex> lk(startup_mtx_);
143-
running_ = true;
144-
}
145-
146-
startup_cond_.notify_one();
147-
148-
// Here other HPX specific functionality could be invoked...
149-
150-
// Now, wait for destructor to be called.
151-
{
152-
std::unique_lock<hpx::spinlock> lk(mtx_);
153-
if (rts_ != nullptr)
154-
cond_.wait(lk);
155-
}
156-
157-
// tell the runtime it's ok to exit
158-
return hpx::finalize();
159-
}
160-
161-
private:
162-
hpx::spinlock mtx_;
163-
hpx::condition_variable_any cond_;
164-
165-
std::mutex startup_mtx_;
166-
std::condition_variable startup_cond_;
167-
bool running_;
168-
169-
hpx::runtime* rts_;
170-
};
171-
17269
// This class demonstrates how to initialize a console instance of HPX
17370
// (locality 0). In order to create an HPX instance which connects to a running
17471
// HPX application two changes have to be made:
@@ -189,25 +86,61 @@ class manage_global_runtime_impl
18986
// sequencing of destructors.
19087
class manage_global_runtime
19188
{
192-
manage_global_runtime_impl& get()
89+
struct init
90+
{
91+
hpx::manage_runtime rts;
92+
93+
init()
94+
{
95+
#if defined(HPX_WINDOWS)
96+
hpx::detail::init_winsocket();
97+
#endif
98+
99+
hpx::init_params init_args;
100+
init_args.cfg = {
101+
// make sure hpx_main is always executed
102+
"hpx.run_hpx_main!=1",
103+
// allow for unknown command line options
104+
"hpx.commandline.allow_unknown!=1",
105+
// disable HPX' short options
106+
"hpx.commandline.aliasing!=0",
107+
};
108+
init_args.mode = hpx::runtime_mode::default_;
109+
110+
if (!rts.start(__argc, __argv, init_args))
111+
{
112+
// Something went wrong while initializing the runtime.
113+
// This early we can't generate any output, just bail out.
114+
std::abort();
115+
}
116+
}
117+
118+
~init()
119+
{
120+
// Something went wrong while stopping the runtime. Ignore.
121+
(void) rts.stop();
122+
}
123+
};
124+
125+
hpx::manage_runtime& get()
193126
{
194-
static thread_local manage_global_runtime_impl m;
195-
return m;
127+
static thread_local init m;
128+
return m.rts;
196129
}
197130

198131
hpx::execution_base::agent_base& agent =
199132
hpx::execution_base::detail::get_default_agent();
200-
manage_global_runtime_impl& m = get();
133+
hpx::manage_runtime& m = get();
201134

202135
public:
203136
void register_thread(char const* name)
204137
{
205-
m.register_thread(name);
138+
hpx::register_thread(m.get_runtime_ptr(), name);
206139
}
207140

208141
void unregister_thread()
209142
{
210-
m.unregister_thread();
143+
hpx::unregister_thread(m.get_runtime_ptr());
211144
}
212145
};
213146

init/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ set(hpx_init_HEADERS
1010
""
1111
CACHE INTERNAL "Headers for libhpx_init." FORCE
1212
)
13-
list(APPEND hpx_init_HEADERS hpx/hpx_main_impl.hpp)
13+
list(APPEND hpx_init_HEADERS hpx/hpx_main_impl.hpp hpx/manage_runtime.hpp)
1414
set(hpx_init_SOURCES
1515
""
1616
CACHE INTERNAL "Sources for libhpx_init." FORCE
@@ -25,6 +25,7 @@ list(
2525
hpx_user_main.cpp
2626
hpx_user_main_argc_argv.cpp
2727
main.cpp
28+
manage_runtime.cpp
2829
)
2930

3031
# make source groups
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright (c) 2025 Agustin Berge
2+
// Copyright (c) 2016-2022 Hartmut Kaiser
3+
//
4+
// SPDX-License-Identifier: BSL-1.0
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
8+
/// \file manage_runtime.hpp
9+
10+
#pragma once
11+
12+
#include <hpx/config.hpp>
13+
14+
#include <hpx/condition_variable.hpp>
15+
#include <hpx/init.hpp>
16+
#include <hpx/manage_runtime.hpp>
17+
#include <hpx/modules/runtime_local.hpp>
18+
#include <hpx/mutex.hpp>
19+
#include <hpx/thread.hpp>
20+
21+
#include <mutex>
22+
23+
namespace hpx {
24+
25+
/// \brief Manages starting/stopping the HPX runtime system.
26+
///
27+
/// An instance of this class may be used to start the HPX runtime system.
28+
class manage_runtime
29+
{
30+
public:
31+
/// Starts the runtime system.
32+
///
33+
/// \param argc [in] The number of command line arguments passed
34+
/// in \p argv. This is usually the unchanged value as
35+
/// passed by the operating system (to `main()`).
36+
/// \param argv [in] The command line arguments for this
37+
/// application, usually that is the value as passed
38+
/// by the operating system (to `main()`).
39+
/// \param params [in] The parameters to the \a hpx::init function
40+
/// (See documentation of \a hpx::init_params)
41+
///
42+
/// \returns The function returns `true` if command line
43+
/// processing succeeded and the runtime system was
44+
/// started successfully. It will return `false`
45+
/// otherwise.
46+
///
47+
/// \note The created runtime system instance will be
48+
/// executed in console or worker mode depending on the
49+
/// command line arguments passed in `argc`/`argv`. If not
50+
/// command line arguments are passed, console mode is
51+
/// assumed.
52+
///
53+
/// \note If no command line arguments are passed the HPX
54+
/// runtime system will not support any of the default
55+
/// command line options as described in the section
56+
/// 'HPX Command Line Options'.
57+
///
58+
/// \note This function will block and wait for the runtime
59+
/// system to start before returning to the caller.
60+
bool start(int argc, char** argv,
61+
init_params const& init_args = init_params());
62+
63+
/// Stops the runtime system.
64+
///
65+
/// \returns This function will always return zero.
66+
///
67+
/// \note The runtime system instance must have been
68+
/// previously started by a successful call to
69+
/// `start()`.
70+
///
71+
/// \note This function will block and wait for the runtime
72+
/// system to stop before returning to the caller.
73+
int stop();
74+
75+
/// \returns A pointer to the runtime system if an instance is
76+
/// running, otherwise `nullptr`.
77+
runtime* get_runtime_ptr() const noexcept
78+
{
79+
return rts_;
80+
}
81+
82+
private:
83+
// Main HPX thread, does nothing but wait for the application to exit
84+
int hpx_main(int, char*[]);
85+
86+
private:
87+
bool running_ = false;
88+
runtime* rts_ = nullptr;
89+
90+
std::mutex startup_mtx_;
91+
std::condition_variable startup_cond_;
92+
93+
spinlock stop_mtx_;
94+
condition_variable_any stop_cond_;
95+
};
96+
} // namespace hpx

init/src/manage_runtime.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) 2025 Agustin Berge
2+
// Copyright (c) 2016-2022 Hartmut Kaiser
3+
//
4+
// SPDX-License-Identifier: BSL-1.0
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
8+
/// \file manage_runtime.hpp
9+
10+
#include <hpx/config.hpp>
11+
12+
#include <hpx/assert.hpp>
13+
#include <hpx/condition_variable.hpp>
14+
#include <hpx/functional.hpp>
15+
#include <hpx/init.hpp>
16+
#include <hpx/manage_runtime.hpp>
17+
#include <hpx/modules/runtime_local.hpp>
18+
#include <hpx/mutex.hpp>
19+
#include <hpx/thread.hpp>
20+
21+
#include <mutex>
22+
23+
namespace hpx {
24+
25+
bool manage_runtime::start(
26+
int argc, char** argv, init_params const& init_args)
27+
{
28+
HPX_ASSERT(!running_);
29+
30+
std::function<int(int, char**)> start_function =
31+
bind_front(&manage_runtime::hpx_main, this);
32+
33+
bool const ret = hpx::start(start_function, argc, argv, init_args);
34+
if (!ret)
35+
return ret;
36+
37+
running_ = true;
38+
39+
// wait for the main HPX thread (hpx_main below) to have started running
40+
std::unique_lock<std::mutex> lk(startup_mtx_);
41+
startup_cond_.wait(lk, [&] { return rts_ != nullptr; });
42+
43+
return ret;
44+
}
45+
46+
int manage_runtime::stop()
47+
{
48+
HPX_ASSERT(running_);
49+
50+
running_ = false;
51+
52+
// signal to `hpx_main` below to tear down the runtime
53+
{
54+
std::lock_guard<spinlock> lk(stop_mtx_);
55+
rts_ = nullptr;
56+
}
57+
stop_cond_.notify_one();
58+
59+
// wait for the runtime to exit
60+
return hpx::stop();
61+
}
62+
63+
int manage_runtime::hpx_main(int, char*[])
64+
{
65+
// signal to `start` that thread has started running.
66+
{
67+
std::lock_guard<std::mutex> lk(startup_mtx_);
68+
rts_ = hpx::get_runtime_ptr();
69+
}
70+
startup_cond_.notify_one();
71+
72+
// wait for `stop` to be called.
73+
{
74+
std::unique_lock<spinlock> lk(stop_mtx_);
75+
stop_cond_.wait(lk, [&] { return rts_ == nullptr; });
76+
}
77+
78+
// tell the runtime it's ok to exit
79+
return hpx::finalize();
80+
}
81+
} // namespace hpx

libs/full/init_runtime/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
88

99
set(init_runtime_headers
10-
hpx/init.hpp
1110
hpx/hpx_finalize.hpp
1211
hpx/hpx_init.hpp
1312
hpx/hpx_init_impl.hpp
@@ -17,6 +16,7 @@ set(init_runtime_headers
1716
hpx/hpx_start_impl.hpp
1817
hpx/hpx_suspend.hpp
1918
hpx/hpx_user_main_config.hpp
19+
hpx/init.hpp
2020
hpx/init_runtime/detail/init_logging.hpp
2121
hpx/init_runtime/detail/run_or_start.hpp
2222
)

0 commit comments

Comments
 (0)