• 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

24.49
/libs/core/serialization/src/detail/polymorphic_id_factory.cpp
1
//  Copyright (c) 2015 Anton Bikineev
2
//  Copyright (c) 2014 Thomas Heller
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0.
6
//  See accompanying file LICENSE_1_0.txt or copy at
7
//  http://www.boost.org/LICENSE_1_0.txt)
8

9
#include <hpx/config.hpp>
10
#include <hpx/assert.hpp>
11
#include <hpx/modules/errors.hpp>
12
#include <hpx/serialization/detail/polymorphic_id_factory.hpp>
13

14
#include <algorithm>
15
#include <cstddef>
16
#include <cstdint>
17
#include <map>
18
#include <string>
19
#include <utility>
20
#include <vector>
21

22
namespace hpx::serialization::detail {
23

38✔
24
    ///////////////////////////////////////////////////////////////////////////
25
    id_registry& id_registry::instance()
26
    {
38✔
27
        static id_registry inst;
28
        return inst;
29
    }
×
30

31
    polymorphic_id_factory::ctor_t polymorphic_id_factory::get_ctor_function(
×
32
        std::uint32_t const id, [[maybe_unused]] std::string const* name)
33
    {
×
34
        cache_t const& vec = id_registry::instance().cache;
×
35

36
        if (id >= vec.size())    //-V104
×
37
        {
38
            std::string msg("Unknown type descriptor " + std::to_string(id));
×
39
#if defined(HPX_DEBUG)
40
            if (name != nullptr)
×
41
            {
42
                msg += ", for typename " + *name + "\n";
×
43
                msg += collect_registered_typenames();
44
            }
45
#endif
46
            HPX_THROW_EXCEPTION(hpx::error::serialization_error,
47
                "polymorphic_id_factory::create", msg);
×
48
        }
49

50
        ctor_t const ctor = vec[static_cast<std::size_t>(id)];
51
        HPX_ASSERT(ctor != nullptr);    //-V108
×
52
        return ctor;
×
53
    }
×
54

55
    void id_registry::cache_id(std::uint32_t const id, ctor_t const ctor)
×
56
    {
57
        if (id >= cache.size())    //-V104
58
        {
59
            cache.resize(static_cast<std::size_t>(id) + 1, nullptr);
60
            cache[id] = ctor;    //-V108
61
        }
×
62
        else if (cache[id] == nullptr)    //-V108
63
        {
×
64
            cache[id] = ctor;    //-V108
65
        }
×
66
    }
67

68
    void id_registry::register_factory_function(
69
        std::string const& type_name, ctor_t ctor)
70
    {
71
        HPX_ASSERT(ctor != nullptr);
72

73
        typename_to_ctor.emplace(type_name, ctor);
74

×
75
        // populate cache
×
76
        auto const it = typename_to_id.find(type_name);
77
        if (it != typename_to_id.end())
×
78
            cache_id(it->second, ctor);
×
79
    }
80

81
    void id_registry::register_typename(
82
        std::string const& type_name, std::uint32_t id)
32✔
83
    {
84
        HPX_ASSERT(id != invalid_id);
85

32✔
86
        std::pair<typename_to_id_t::iterator, bool> const p =
32✔
87
            typename_to_id.emplace(type_name, id);
88

89
        if (!p.second)
90
        {
32✔
91
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
92
                "polymorphic_id_factory::register_typename",
93
                "failed to insert {} into typename_to_id_t registry",
×
94
                type_name);
×
95
            return;
96
        }
97

98
        // populate cache
99
        auto const it = typename_to_ctor.find(type_name);
32✔
100
        if (it != typename_to_ctor.end())
101
            cache_id(id, it->second);
102

103
        max_id = (std::max) (id, max_id);
×
104
    }
105

32✔
106
    // This makes sure that the registries are consistent.
107
    void id_registry::fill_missing_typenames()
×
108
    {
109
        // Register all type-names and assign missing ids
110
        for (std::string const& str : get_unassigned_typenames())
×
111
            register_typename(str, ++max_id);
112

113
        // Go over all registered mappings from type-names to ids and
×
114
        // fill in missing id to constructor mappings.
115
        for (auto const& [fst, snd] : typename_to_id)
116
        {
38✔
117
            auto const it = typename_to_ctor.find(fst);
118
            if (it != typename_to_ctor.end())
38✔
119
                cache_id(snd, it->second);
120
        }
121

38✔
122
        // Go over all registered mappings from type-names to
123
        // constructors and fill in missing id to constructor mappings.
124
        for (auto const& [fst, snd] : typename_to_ctor)
125
        {
×
126
            typename_to_id_t::const_iterator it = typename_to_id.find(fst);
127
            HPX_ASSERT(it != typename_to_id.end());
128
            cache_id(it->second, snd);    //-V783
129
        }
38✔
130
    }
×
131

132
    std::uint32_t id_registry::try_get_id(std::string const& type_name) const
133
    {
×
134
        auto const it = typename_to_id.find(type_name);
135
        if (it == typename_to_id.end())
136
            return invalid_id;
×
137

138
        return it->second;
139
    }
×
140

141
    std::vector<std::string> id_registry::get_unassigned_typenames() const
×
142
    {
143
        std::vector<std::string> result;
×
144

145
        // O(N log(M)) ?
×
146
        for (auto const& [fst, snd] : typename_to_ctor)
147
        {
148
            if (!typename_to_id.count(fst))
149
            {
150
                result.push_back(fst);
×
151
            }
152
        }
153

×
154
        return result;
155
    }
156

157
    ///////////////////////////////////////////////////////////////////////////
158
    polymorphic_id_factory& polymorphic_id_factory::instance()
159
    {
160
        hpx::util::static_<polymorphic_id_factory> factory;
161
        return factory.get();
162
    }
163

164
    std::uint32_t polymorphic_id_factory::get_id(std::string const& type_name)
165
    {
166
        std::uint32_t const id = id_registry::instance().try_get_id(type_name);
167

168
        if (id == id_registry::invalid_id)
169
        {
170
            HPX_THROW_EXCEPTION(hpx::error::serialization_error,
171
                "polymorphic_id_factory::get_id", "Unknown typename: {}",
172
                type_name);
×
173
        }
174

175
        return id;
176
    }
177

178
    std::string polymorphic_id_factory::collect_registered_typenames()
179
    {
180
#if defined(HPX_DEBUG)
181
        std::string msg("known constructors:\n");
182

183
        for (auto const& [fst, snd] : id_registry::instance().typename_to_ctor)
184
        {
185
            msg += fst + "\n";
186
        }
187

188
        msg += "\nknown typenames:\n";
189
        for (auto const& [fst, snd] : id_registry::instance().typename_to_id)
190
        {
191
            msg += fst + " (";
192
            msg += std::to_string(snd) + ")\n";
193
        }
194

195
        return msg;
196
#else
197
        return std::string();
198
#endif
199
    }
200
}    // namespace hpx::serialization::detail
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

© 2026 Coveralls, Inc