• 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

80.34
/libs/core/program_options/src/variables_map.cpp
1
//  Copyright Vladimir Prus 2002-2004.
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0.
5
//  (See accompanying file LICENSE_1_0.txt
6
//  or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/program_options/config.hpp>
9
#include <hpx/assert.hpp>
10
#include <hpx/datastructures/any.hpp>
11
#include <hpx/program_options/options_description.hpp>
12
#include <hpx/program_options/parsers.hpp>
13
#include <hpx/program_options/value_semantic.hpp>
14
#include <hpx/program_options/variables_map.hpp>
15

16
#include <cstddef>
17
#include <map>
18
#include <memory>
19
#include <set>
20
#include <string>
21
#include <vector>
22

23
namespace hpx::program_options {
24

25
    // First, performs semantic actions for 'oa'. Then, stores in 'm' all
26
    // options that are defined in 'desc'.
27
    HPX_CORE_EXPORT
28
    void store(parsed_options const& options, variables_map& xm, bool utf8)
4,317✔
29
    {
30
        // TODO: what if we have different definition for the same option name
31
        // during different calls 'store'.
32
        HPX_ASSERT(options.description);
4,317✔
33
        options_description const& desc = *options.description;
4,317✔
34

35
        // We need to access map's operator[], not the overridden version
36
        // variables_map. Ehmm.. messy.
37
        std::map<std::string, variable_value>& m = xm;
4,317✔
38

39
        std::set<std::string> new_final;
4,317✔
40

41
        // Declared once, to please Intel in VC++ mode;
42
        std::size_t i;
43

44
        // Declared here so can be used to provide context for exceptions
45
        std::string option_name;
4,317✔
46
        std::string original_token;
4,317✔
47

48
        try
49
        {
50
            // First, convert/store all given options
51
            for (i = 0; i < options.options.size(); ++i)
19,379✔
52
            {
53
                auto const& opts = options.options[i];
15,068✔
54
                option_name = opts.string_key;
15,068✔
55
                // Skip positional options without name
56
                if (option_name.empty())
15,068✔
57
                    continue;
423✔
58

59
                // Ignore unregistered option. The 'unregistered' field can be
60
                // true only if user has explicitly asked to allow unregistered
61
                // options. We can't store them to variables map (lacking any
62
                // information about paring), so just ignore them.
63
                if (opts.unregistered)
14,645✔
64
                    continue;
615✔
65

66
                // If option has final value, skip this assignment
67
                if (xm.m_final.count(option_name))
14,030✔
68
                    continue;
1✔
69

70
                original_token = !opts.original_tokens.empty() ?
28,058✔
71
                    opts.original_tokens[0] :
13,994✔
72
                    "";
35✔
73
                option_description const& d =
14,029✔
74
                    desc.find(option_name, false, false, false);
14,029✔
75

76
                variable_value& v = m[option_name];
14,029✔
77
                if (v.defaulted())
14,029✔
78
                {
79
                    // Explicit assignment here erases defaulted value
80
                    v = variable_value();
2✔
81
                }
2✔
82

83
                auto const& semantic = d.semantic();
14,029✔
84
                semantic->parse(v.value(), opts.value, utf8);
14,029✔
85

86
                v.m_value_semantic = semantic;
14,023✔
87

88
                // The option is not composing, and the value is explicitly
89
                // provided. Ignore values of this option for subsequent calls
90
                // to 'store'. We store this to a temporary set, so that several
91
                // assignment inside *this* 'store' call are allowed.
92
                if (!semantic->is_composing())
14,023✔
93
                    new_final.insert(option_name);
11,737✔
94
            }
14,029✔
95
        }
4,317✔
96
        catch (error_with_option_name& e)
97
        {
98
            // add context and rethrow
99
            e.add_context(
12✔
100
                option_name, original_token, options.m_options_prefix);
6✔
101
            throw;
6✔
102
        }
6✔
103

104
        xm.m_final.insert(new_final.begin(), new_final.end());
4,311✔
105

106
        // Second, apply default values and store required options.
107
        std::vector<std::shared_ptr<option_description>> const& all =
4,311✔
108
            desc.options();
4,311✔
109
        for (i = 0; i < all.size(); ++i)
189,594✔
110
        {
111
            option_description const& d = *all[i];
185,283✔
112
            std::string key = d.key("");
185,283✔
113
            // FIXME: this logic relies on knowledge of option_description
114
            // internals. The 'key' is empty if options description contains
115
            // '*'. In that case, default value makes no sense at all.
116
            if (key.empty())
185,283✔
117
            {
118
                continue;
×
119
            }
120
            if (m.count(key) == 0)
185,283✔
121
            {
122
                hpx::any_nonser def;
172,469✔
123
                if (d.semantic()->apply_default(def))
172,469✔
124
                {
125
                    m[key] = variable_value(def, true);
5,556✔
126
                    m[key].m_value_semantic = d.semantic();
5,556✔
127
                }
5,556✔
128
            }
172,469✔
129

130
            // add empty value if this is an required option
131
            if (d.semantic()->is_required())
185,283✔
132
            {
133
                // For option names specified in multiple ways, e.g. on the
134
                // command line, config file etc, the following precedence rules
135
                // apply: "--"  >  ("-" or "/")  >  ""
136
                // Precedence is set conveniently by a single call to length()
137
                std::string canonical_name =
138
                    d.canonical_display_name(options.m_options_prefix);
15✔
139
                if (canonical_name.length() > xm.m_required[key].length())
15✔
140
                    xm.m_required[key] = HPX_MOVE(canonical_name);
11✔
141
            }
15✔
142
        }
185,283✔
143
    }
4,329✔
144

145
    void store(wparsed_options const& options, variables_map& m)
3✔
146
    {
147
        store(options.utf8_encoded_options, m, true);
3✔
148
    }
3✔
149

150
    void notify(variables_map& vm)
4,287✔
151
    {
152
        vm.notify();
4,287✔
153
    }
4,287✔
154

155
    abstract_variables_map::abstract_variables_map()
4,320✔
156
      : m_next(nullptr)
4,320✔
157
    {
4,320✔
158
    }
4,320✔
159

160
    abstract_variables_map::abstract_variables_map(
×
161
        abstract_variables_map const* next)
162
      : m_next(next)
×
163
    {
×
164
    }
×
165

166
    variable_value const& abstract_variables_map::operator[](
16,912✔
167
        std::string const& name) const
168
    {
169
        variable_value const& v = get(name);
16,912✔
170
        if (v.empty() && m_next)
16,912✔
171
            return (*m_next)[name];
×
172
        else if (v.defaulted() && m_next)
16,912✔
173
        {
174
            variable_value const& v2 = (*m_next)[name];
×
175
            if (!v2.empty() && !v2.defaulted())
×
176
                return v2;
×
177
            else
178
                return v;
×
179
        }
180
        else
181
        {
182
            return v;
16,912✔
183
        }
184
    }
16,912✔
185

186
    void abstract_variables_map::next(abstract_variables_map* next)
×
187
    {
188
        m_next = next;
×
189
    }
×
190

191
    variables_map::variables_map() {}
4,320✔
192

193
    variables_map::variables_map(abstract_variables_map const* next)
×
194
      : abstract_variables_map(next)
×
195
    {
×
196
    }
×
197

198
    void variables_map::clear()
×
199
    {
200
        std::map<std::string, variable_value>::clear();
×
201
        m_final.clear();
×
202
        m_required.clear();
×
203
    }
×
204

205
    variable_value const& variables_map::get(std::string const& name) const
16,912✔
206
    {
207
        static variable_value empty;
16,912✔
208
        const_iterator i = this->find(name);
16,912✔
209
        if (i == this->end())
16,912✔
210
            return empty;
×
211
        else
212
            return i->second;
16,912✔
213
    }
16,912✔
214

215
    void variables_map::notify()
4,287✔
216
    {
217
        // This checks if all required options occur
218
        for (std::map<std::string, std::string>::const_iterator r =
4,292✔
219
                 m_required.begin();
4,287✔
220
             r != m_required.end(); ++r)
4,292✔
221
        {
222
            std::string const& opt = r->first;
6✔
223
            std::string const& display_opt = r->second;
6✔
224
            std::map<std::string, variable_value>::const_iterator iter =
225
                find(opt);
6✔
226
            if (iter == end() || iter->second.empty())
6✔
227
            {
228
                throw required_option(display_opt);
1✔
229
            }
230
        }
5✔
231

232
        // Lastly, run notify actions.
233
        for (auto& k : *this)
22,604✔
234
        {
235
            /* Users might wish to use variables_map to store their own values
236
               that are not parsed, and therefore will not have value_semantics
237
               defined. Do not crash on such values. In multi-module programs,
238
               one module might add custom values, and the 'notify' function
239
               will be called after that, so we check that value_sematics is
240
               not NULL. See:
241
                   https://svn.boost.org/trac/boost/ticket/2782
242
            */
243
            if (k.second.m_value_semantic)
18,318✔
244
                k.second.m_value_semantic->notify(k.second.value());
18,318✔
245
        }
246
    }
4,286✔
247
}    // namespace hpx::program_options
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