• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/examples/quickstart/init_globally.cpp
1
//  Copyright (c) 2016-2022 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
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
// This example demonstrates several things:
8
//
9
// - How to initialize (and terminate) the HPX runtime from a global object
10
//   (see the type `manage_global_runtime' below)
11
// - How to register and unregister any (kernel) thread with the HPX runtime
12
// - How to launch an HPX thread from any (registered) kernel thread and
13
//   how to wait for the HPX thread to run to completion before continuing.
14
//   Any value returned from the HPX thread will be marshaled back to the
15
//   calling (kernel) thread.
16
//
17
// This scheme is generally useful if HPX should be initialized from a shared
18
// library and the main executable might not even be aware of this.
19

20
#include <hpx/condition_variable.hpp>
21
#include <hpx/functional.hpp>
22
#include <hpx/manage_runtime.hpp>
23
#include <hpx/modules/runtime_local.hpp>
24
#include <hpx/mutex.hpp>
25
#include <hpx/thread.hpp>
26

27
#include <mutex>
28
#include <string>
29
#include <vector>
30

31
///////////////////////////////////////////////////////////////////////////////
32
// Store the command line arguments in global variables to make them available
33
// to the startup code.
34

35
#if defined(linux) || defined(__linux) || defined(__linux__)
36

37
int __argc = 0;
38
char** __argv = nullptr;
39

40
void set_argc_argv(int argc, char* argv[], char*[])
1✔
41
{
42
    __argc = argc;
1✔
43
    __argv = argv;
1✔
44
}
1✔
45

46
__attribute__((section(".preinit_array"))) void (*set_global_argc_argv)(
47
    int, char*[], char*[]) = &set_argc_argv;
48

49
#elif defined(__APPLE__)
50

51
#include <crt_externs.h>
52

53
inline int get_arraylen(char** argv)
54
{
55
    int count = 0;
56
    if (nullptr != argv)
57
    {
58
        while (nullptr != argv[count])
59
            ++count;
60
    }
61
    return count;
62
}
63

64
int __argc = get_arraylen(*_NSGetArgv());
65
char** __argv = *_NSGetArgv();
66

67
#endif
68

69
// This class demonstrates how to initialize a console instance of HPX
70
// (locality 0). In order to create an HPX instance which connects to a running
71
// HPX application two changes have to be made:
72
//
1✔
73
//  - replace hpx::runtime_mode::default_ with hpx::runtime_mode::connect
1✔
74
//  - replace hpx::finalize() with hpx::disconnect()
1✔
75
//
76
// Note that the mode runtime_mode::default_ corresponds to runtime_mode::console
77
// if the distributed runtime is enabled, and runtime_mode::local otherwise.
78
//
79
// The separation of the implementation into manage_global_runtime and
80
// manage_global_runtime_impl ensures that the manage_global_runtime_impl
81
// destructor is called before the thread_local default agent is destructed,
82
// allowing the former to call yield if necessary while waiting for the runtime
83
// to shut down. This is done by accessing the default agent before accessing
84
// the manage_global_runtime object. Although the latter is thread_local, only
85
// one instance will be created. It is thread_local only to ensure the correct
86
// sequencing of destructors.
4✔
87
class manage_global_runtime
88
{
89
    struct init
90
    {
91
        hpx::manage_runtime rts;
92

1✔
93
        init()
1✔
94
        {
1✔
95
#if defined(HPX_WINDOWS)
96
            hpx::detail::init_winsocket();
2✔
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",
1✔
105
                // disable HPX' short options
1✔
106
                "hpx.commandline.aliasing!=0",
×
107
            };
4✔
108
            init_args.mode = hpx::runtime_mode::default_;
109

1✔
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.
1✔
114
                std::abort();
1✔
115
            }
116
        }
117

1✔
118
        ~init()
119
        {
120
            // Something went wrong while stopping the runtime. Ignore.
1✔
121
            (void) rts.stop();
1✔
122
        }
123
    };
124

125
    hpx::manage_runtime& get()
126
    {
1✔
127
        static thread_local init m;
128
        return m.rts;
129
    }
130

1✔
131
    hpx::execution_base::agent_base& agent =
132
        hpx::execution_base::detail::get_default_agent();
133
    hpx::manage_runtime& m = get();
134

135
public:
1✔
136
    void register_thread(char const* name)
137
    {
138
        hpx::register_thread(m.get_runtime_ptr(), name);
1✔
139
    }
140

141
    void unregister_thread()
142
    {
1✔
143
        hpx::unregister_thread(m.get_runtime_ptr());
1✔
144
    }
145
};
146

1✔
147
// This global object will initialize HPX in its constructor and make sure HPX
148
// stops running in its destructor.
149
manage_global_runtime init;
150

151
///////////////////////////////////////////////////////////////////////////////
152
struct thread_registration_wrapper
1✔
153
{
1✔
154
    thread_registration_wrapper(char const* name)
1✔
155
    {
156
        // Register this thread with HPX, this should be done once for
157
        // each external OS-thread intended to invoke HPX functionality.
158
        // Calling this function more than once will silently fail (will
1✔
159
        // return false).
160
        init.register_thread(name);
161
    }
162
    ~thread_registration_wrapper()
163
    {
164
        // Unregister the thread from HPX, this should be done once in the
165
        // end before the external thread exists.
166
        init.unregister_thread();
167
    }
168
};
169

170
///////////////////////////////////////////////////////////////////////////////
171
// These functions will be executed as HPX threads.
172
void hpx_thread_func1()
173
{
174
    // All of the HPX functionality is available here, including hpx::async,
175
    // hpx::future, and friends.
176

177
    // As an example, just sleep for one second.
178
    hpx::this_thread::sleep_for(std::chrono::seconds(1));
179
}
180

181
int hpx_thread_func2(int arg)
182
{
183
    // All of the HPX functionality is available here, including hpx::async,
184
    // hpx::future, and friends.
185

186
    // As an example, just sleep for one second.
187
    hpx::this_thread::sleep_for(std::chrono::seconds(1));
188

189
    // Simply return the argument.
190
    return arg;
191
}
192

1✔
193
///////////////////////////////////////////////////////////////////////////////
194
// This code will be executed by a system thread.
1✔
195
void thread_func()
1✔
196
{
197
    // Register this (kernel) thread with the HPX runtime (unregister at exit).
198
    // Use a unique name for each of the created threads (could be derived from
199
    // std::this_thread::get_id()).
200
    thread_registration_wrapper register_thread("thread_func");
201

202
    // Now, a limited number of HPX API functions can be called.
203

204
    // Create an HPX thread (returning an int) and wait for it to run to
205
    // completion.
1✔
206
    int result = hpx::run_as_hpx_thread(&hpx_thread_func2, 42);
207

208
    // Create an HPX thread (returning void) and wait for it to run to
209
    // completion.
210
    if (result == 42)
1✔
211
        hpx::run_as_hpx_thread(&hpx_thread_func1);
212
}
213

214
///////////////////////////////////////////////////////////////////////////////
215
int main()
216
{
217
    // Start a new (kernel) thread to demonstrate thread registration with HPX.
218
    std::thread t(&thread_func);
219

220
    // The main thread was automatically registered with the HPX runtime,
221
    // no explicit registration for this thread is necessary.
222
    hpx::run_as_hpx_thread(&hpx_thread_func1);
223

224
    // wait for the (kernel) thread to run to completion
225
    t.join();
226

227
    return 0;
228
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc