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

STEllAR-GROUP / hpx / #862

10 Jan 2023 05:30PM UTC coverage: 86.582% (-0.05%) from 86.634%
#862

push

StellarBot
Merge #6130

6130: Remove the mutex lock in the critical path of get_partitioner. r=hkaiser a=JiakunYan

Remove the mutex lock in the critical path of hpx::resource::detail::get_partitioner.

The protected variable `partitioner_ref` is only set once during initialization.

Co-authored-by: Jiakun Yan <jiakunyan1998@gmail.com>

6 of 6 new or added lines in 1 file covered. (100.0%)

174767 of 201851 relevant lines covered (86.58%)

2069816.07 hits per line

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

34.48
/libs/core/asio/src/asio_util.cpp
1
//  Copyright (c) 2007-2017 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
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
// hpxinspect:nodeprecatedinclude:boost/system/error_code.hpp
9
// hpxinspect:nodeprecatedname:boost::system::error_code
10
// hpxinspect:nodeprecatedinclude:boost/system/system_error.hpp
11
// hpxinspect:nodeprecatedname:boost::system::system_error
12

13
#include <hpx/config.hpp>
14
#include <hpx/asio/asio_util.hpp>
15
#include <hpx/util/from_string.hpp>
16

17
#include <cstdint>
18
#include <string>
19

20
#include <hpx/config/asio.hpp>
21
#include <hpx/assert.hpp>
22
#include <hpx/modules/errors.hpp>
23

24
#include <asio/io_context.hpp>
25
#include <asio/ip/address_v4.hpp>
26
#include <asio/ip/address_v6.hpp>
27
#include <asio/ip/host_name.hpp>
28
#include <asio/ip/tcp.hpp>
29

30
#include <ctime>
31
#include <exception>
32
#include <system_error>
33

34
#if defined(HPX_WINDOWS) && !defined(HPX_HAVE_STATIC_LINKING)
35
// Prevent asio from initializing Winsock, the object must be constructed
36
// before any Asio's own global objects. With MSVC, this may be accomplished
37
// by adding the following code to the DLL:
38

39
#if defined(HPX_MSVC_WARNING_PRAGMA)
40
#pragma warning(push)
41
#pragma warning(disable : 4073)
42
#endif
43
#pragma init_seg(lib)
44
asio::detail::winsock_init<>::manual manual_winsock_init;
45
#if defined(HPX_MSVC_WARNING_PRAGMA)
46
#pragma warning(pop)
47
#endif
48
#endif
49

50
///////////////////////////////////////////////////////////////////////////////
51
namespace hpx::util {
52

53
    ///////////////////////////////////////////////////////////////////////////
54
    bool get_endpoint(std::string const& addr, std::uint16_t port,
3,566✔
55
        asio::ip::tcp::endpoint& ep, bool force_ipv4)
56
    {
57
        using namespace asio::ip;
58
        std::error_code ec;
3,558✔
59
        address_v4 addr4 = address_v4::from_string(addr.c_str(), ec);    //-V821
3,558✔
60
        if (!ec)
3,558✔
61
        {    // it's an IPV4 address
62
            ep = tcp::endpoint(address(addr4), port);
3,557✔
63
            return true;
3,557✔
64
        }
65

66
        if (!force_ipv4)
×
67
        {
68
            address_v6 addr6 =    //-V821
69
                address_v6::from_string(addr.c_str(), ec);
×
70
            if (!ec)
×
71
            {    // it's an IPV6 address
72
                ep = tcp::endpoint(address(addr6), port);
×
73
                return true;
×
74
            }
75
        }
×
76
        return false;
×
77
    }
3,556✔
78

79
    ///////////////////////////////////////////////////////////////////////////
80
    std::string get_endpoint_name(asio::ip::tcp::endpoint const& ep)
2,392✔
81
    {
82
        return ep.address().to_string();
2,392✔
83
    }
84

85
    ///////////////////////////////////////////////////////////////////////////
86
    // properly resolve a give host name to the corresponding IP address
87
    asio::ip::tcp::endpoint resolve_hostname(std::string const& hostname,
2,392✔
88
        std::uint16_t port, asio::io_context& io_service, bool force_ipv4)
89
    {
90
        using asio::ip::tcp;
91

92
        // collect errors here
93
        exception_list errors;
2,392✔
94

95
        // try to directly create an endpoint from the address
96
        try
97
        {
98
            tcp::endpoint ep;
2,392✔
99
            if (util::get_endpoint(hostname, port, ep))
2,392✔
100
                return ep;
2,392✔
101
        }
×
102
        catch (std::system_error const&)
103
        {
104
            errors.add(std::current_exception());
×
105
        }
×
106

107
        // it's not an address, try to treat it as a host name
108
        try
109
        {
110
            // resolve the given address
111
            tcp::resolver resolver(io_service);
×
112
            tcp::resolver::query query(hostname, std::to_string(port));
×
113

114
            asio::ip::tcp::resolver::iterator it = resolver.resolve(query);
×
115

116
            // skip ipv6 results, if required
117
            if (force_ipv4)
×
118
            {
119
                while (it != tcp::resolver::iterator() &&
×
120
                    !it->endpoint().address().is_v4())
×
121
                {
122
                    ++it;
×
123
                }
124
            }
×
125

126
            HPX_ASSERT(it != asio::ip::tcp::resolver::iterator());
×
127
            return *it;
×
128
        }
×
129
        catch (std::system_error const&)
130
        {
131
            errors.add(std::current_exception());
×
132
        }
×
133

134
        // report errors
135
        HPX_THROW_EXCEPTION(hpx::error::network_error, "util::resolve_hostname",
×
136
            "{} (while trying to resolve: {}:{})", errors.get_message(),
137
            hostname, port);
138
        return tcp::endpoint();
139
    }
2,392✔
140

141
    ///////////////////////////////////////////////////////////////////////////
142
    // return the public IP address of the local node
143
    std::string resolve_public_ip_address()
2✔
144
    {
145
        using asio::ip::tcp;
146

147
        // collect errors here
148
        exception_list errors;
2✔
149

150
        try
151
        {
152
            asio::io_context io_service;
2✔
153
            tcp::resolver resolver(io_service);
2✔
154
            tcp::resolver::query query(asio::ip::host_name(), "");
2✔
155
            tcp::resolver::iterator it = resolver.resolve(query);
2✔
156
            tcp::endpoint endpoint = *it;
2✔
157
            return endpoint.address().to_string();
2✔
158
        }
2✔
159
        catch (std::system_error const&)
160
        {
161
            errors.add(std::current_exception());
×
162
        }
×
163

164
        // report errors
165
        HPX_THROW_EXCEPTION(hpx::error::network_error,
×
166
            "util::resolve_public_ip_address",
167
            "{} (while trying to resolve public ip address)",
168
            errors.get_message());
169
        return "";
170
    }
2✔
171

172
    ///////////////////////////////////////////////////////////////////////
173
    // Take an ip v4 or v6 address and "standardize" it for comparison checks
174
    // note that this code doesn't work as expected if we use the boost
175
    // inet_pton functions on linux. see issue #2177 for further info
176
    std::string cleanup_ip_address(std::string const& addr)
899,426✔
177
    {
178
        char buf[sizeof(struct in6_addr)];
179
        int i = 0, domain[2] = {AF_INET, AF_INET6};
899,428✔
180
        char str[INET6_ADDRSTRLEN];
181

182
#if defined(HPX_WINDOWS)
183
        unsigned long scope_id;
184
        std::error_code ec;
185
#endif
186

187
        for (i = 0; i < 2; ++i)
899,426✔
188
        {
189
#if defined(HPX_WINDOWS)
190
            int s = asio::detail::socket_ops::inet_pton(
191
                domain[i], &addr[0], buf, &scope_id, ec);
192
            if (s > 0 && !ec)
193
                break;
194
#else
195
            int s = inet_pton(domain[i], &addr[0], buf);
899,447✔
196
            if (s > 0)
899,447✔
197
                break;
899,448✔
198
#endif
199
        }
×
200
        if (i == 2)
899,445✔
201
        {
202
            HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "cleanup_ip_address",
×
203
                "Invalid IP address string");
204
        }
205

206
#if defined(HPX_WINDOWS)
207
        if (asio::detail::socket_ops::inet_ntop(
208
                domain[i], buf, str, INET6_ADDRSTRLEN, scope_id, ec) == nullptr)
209
        {
210
#else
211
        if (inet_ntop(domain[i], buf, str, INET6_ADDRSTRLEN) == nullptr)
899,448✔
212
        {
213
#endif
214
            HPX_THROW_EXCEPTION(hpx::error::bad_parameter, "cleanup_ip_address",
×
215
                "inet_ntop failure");
216
        }
217
        return std::string(str);
899,448✔
218
    }
×
219

220
    endpoint_iterator_type connect_begin(std::string const& address,
888✔
221
        std::uint16_t port, asio::io_context& io_service)
222
    {
223
        using asio::ip::tcp;
224

225
        // collect errors here
226
        exception_list errors;
887✔
227

228
        std::string port_str(std::to_string(port));
887✔
229

230
        // try to directly create an endpoint from the address
231
        try
232
        {
233
            tcp::endpoint ep;
880✔
234
            if (util::get_endpoint(address, port, ep))
887✔
235
            {
236
                return endpoint_iterator_type(
874✔
237
                    tcp::resolver::results_type::create(ep, address, port_str));
880✔
238
            }
239
        }
×
240
        catch (std::system_error const&)
241
        {
242
            errors.add(std::current_exception());
×
243
        }
×
244

245
        // it's not an address, try to treat it as a host name
246
        try
247
        {
248
            // resolve the given address
249
            tcp::resolver resolver(io_service);
×
250
            tcp::resolver::query query(
×
251
                !address.empty() ? address : asio::ip::host_name(), port_str);
×
252

253
            return endpoint_iterator_type(resolver.resolve(query));
×
254
        }
×
255
        catch (std::system_error const&)
256
        {
257
            errors.add(std::current_exception());
×
258
        }
×
259

260
        // report errors
261
        HPX_THROW_EXCEPTION(hpx::error::network_error, "connect_begin",
×
262
            "{} (while trying to connect to: {}:{})", errors.get_message(),
263
            address, port);
264

265
        return endpoint_iterator_type();
266
    }
879✔
267

268
    endpoint_iterator_type accept_begin(std::string const& address,
284✔
269
        std::uint16_t port, asio::io_context& io_service)
270
    {
271
        using asio::ip::tcp;
272

273
        // collect errors here
274
        exception_list errors;
284✔
275

276
        std::string port_str(std::to_string(port));
284✔
277

278
        // try to directly create an endpoint from the address
279
        try
280
        {
281
            tcp::endpoint ep;
284✔
282
            if (util::get_endpoint(address, port, ep))
284✔
283
            {
284
                return endpoint_iterator_type(
284✔
285
                    tcp::resolver::results_type::create(ep, address, port_str));
284✔
286
            }
287
        }
×
288
        catch (std::system_error const&)
289
        {
290
            errors.add(std::current_exception());
×
291
        }
×
292

293
        // it's not an address, try to treat it as a host name
294
        try
295
        {
296
            // resolve the given address
297
            tcp::resolver resolver(io_service);
×
298
            tcp::resolver::query query(address, port_str);
×
299

300
            return endpoint_iterator_type(resolver.resolve(query));
×
301
        }
×
302
        catch (std::system_error const&)
303
        {
304
            errors.add(std::current_exception());
×
305
        }
×
306

307
        // it's not a host name either, create a custom iterator allowing to
308
        // filter the returned endpoints, for this we use "localhost" as the
309
        // address to enumerate endpoints
310
        try
311
        {
312
            // resolve the given address
313
            tcp::resolver resolver(io_service);
×
314
            tcp::resolver::query query(asio::ip::host_name(), port_str);
×
315

316
            return endpoint_iterator_type(resolver.resolve(query));
×
317
        }
×
318
        catch (std::system_error const&)
319
        {
320
            errors.add(std::current_exception());
×
321
        }
×
322

323
        // report errors
324
        HPX_THROW_EXCEPTION(hpx::error::network_error, "accept_begin",
×
325
            "{} (while trying to resolve: {}:{}))", errors.get_message(),
326
            address, port);
327
        return endpoint_iterator_type();
328
    }
284✔
329
}    // namespace hpx::util
330

331
///////////////////////////////////////////////////////////////////////////////
332
namespace hpx::util {
333

334
    ///////////////////////////////////////////////////////////////////////////
335
    // Addresses are supposed to have the format <hostname>[:port]
336
    bool split_ip_address(
×
337
        std::string const& v, std::string& host, std::uint16_t& port)
338
    {
339
        std::string::size_type p = v.find_last_of(':');
×
340

341
        std::string tmp_host;
×
342
        std::uint16_t tmp_port = 0;
×
343

344
        try
345
        {
346
            if (p != std::string::npos)
×
347
            {
348
                if (v.find_first_of(':') != p)
×
349
                {
350
                    // IPv6
351
                    std::string::size_type begin_of_address =
×
352
                        v.find_first_of('[');
×
353
                    if (begin_of_address != std::string::npos)
×
354
                    {
355
                        // IPv6 with a port has to be written as: [address]:port
356
                        std::string::size_type end_of_address =
×
357
                            v.find_last_of(']');
×
358
                        if (end_of_address == std::string::npos)
×
359
                            return false;
×
360

361
                        tmp_host =
×
362
                            v.substr(begin_of_address + 1, end_of_address - 1);
×
363
                        if (end_of_address < p)
×
364
                        {
365
                            tmp_port = hpx::util::from_string<std::uint16_t>(
×
366
                                v.substr(p + 1));
×
367
                        }
×
368
                    }
×
369
                    else
370
                    {
371
                        // IPv6 without a port
372
                        tmp_host = v;
×
373
                    }
374
                }
×
375
                else
376
                {
377
                    // IPv4
378
                    tmp_host = v.substr(0, p);
×
379
                    tmp_port =
×
380
                        hpx::util::from_string<std::uint16_t>(v.substr(p + 1));
×
381
                }
382
            }
×
383
            else
384
            {
385
                tmp_host = v;
×
386
            }
387

388
            if (!tmp_host.empty())
×
389
            {
390
                host = tmp_host;
×
391
                if (tmp_port)
×
392
                    port = tmp_port;
×
393
            }
×
394
        }
×
395
        catch (hpx::util::bad_lexical_cast const& /*e*/)
396
        {
397
            // port number is invalid
398
            return false;
×
399
        }
×
400
        return true;
×
401
    }
×
402
}    // namespace hpx::util
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