Skip to content

Commit 40eeda1

Browse files
committed
vertex properties storage alignment
1 parent 56c8060 commit 40eeda1

1 file changed

Lines changed: 48 additions & 60 deletions

File tree

include/gl/graph.hpp

Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class graph final {
8585
using vertex_properties_map_type = std::conditional_t<
8686
traits::c_empty_properties<vertex_properties_type>,
8787
empty_properties_map,
88-
std::vector<std::unique_ptr<vertex_properties_type>>>;
88+
std::vector<vertex_properties_type>>;
8989

9090
using edge_type = typename traits_type::edge_type;
9191
using edge_properties_type = typename traits_type::edge_properties_type;
@@ -100,11 +100,8 @@ class graph final {
100100
graph() = default;
101101

102102
explicit graph(const size_type n_vertices) : _n_vertices(n_vertices), _impl(n_vertices) {
103-
if constexpr (traits::c_non_empty_properties<vertex_properties_type>) {
104-
this->_vertex_properties.reserve(n_vertices);
105-
for (auto _ : this->vertex_ids())
106-
this->_vertex_properties.push_back(std::make_unique<vertex_properties_type>());
107-
}
103+
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
104+
this->_vertex_properties.resize(n_vertices);
108105
}
109106

110107
graph(graph&&) noexcept = default;
@@ -129,10 +126,7 @@ class graph final {
129126
const auto new_vertex_id = static_cast<id_type>(this->_n_vertices++);
130127

131128
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
132-
return vertex_descriptor{
133-
new_vertex_id,
134-
*this->_vertex_properties.emplace_back(std::make_unique<vertex_properties_type>())
135-
};
129+
return vertex_descriptor{new_vertex_id, this->_vertex_properties.emplace_back()};
136130
else
137131
return vertex_descriptor{new_vertex_id};
138132
}
@@ -143,22 +137,16 @@ class graph final {
143137
this->_impl.add_vertex();
144138
return vertex_descriptor{
145139
static_cast<id_type>(this->_n_vertices++),
146-
*this->_vertex_properties.emplace_back(
147-
std::make_unique<vertex_properties_type>(std::move(properties))
148-
)
140+
this->_vertex_properties.emplace_back(std::move(properties))
149141
};
150142
}
151143

152144
void add_vertices(const size_type n) {
153145
this->_impl.add_vertices(n);
154146
this->_n_vertices += n;
155147

156-
if constexpr (traits::c_non_empty_properties<vertex_properties_type>) {
157-
const auto old_size = this->_vertex_properties.size();
158-
this->_vertex_properties.reserve(this->_n_vertices);
159-
for (auto _ = old_size; _ < this->_n_vertices; ++_)
160-
this->_vertex_properties.push_back(std::make_unique<vertex_properties_type>());
161-
}
148+
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
149+
this->_vertex_properties.resize(this->_n_vertices);
162150
}
163151

164152
void add_vertices_with(
@@ -171,12 +159,12 @@ class graph final {
171159
this->_impl.add_vertices(n);
172160
this->_n_vertices += n;
173161

174-
if constexpr (traits::c_non_empty_properties<vertex_properties_type>) {
175-
for (auto& properties : properties_rng)
176-
this->_vertex_properties.emplace_back(
177-
std::make_unique<vertex_properties_type>(properties)
178-
);
179-
}
162+
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
163+
this->_vertex_properties.insert(
164+
this->_vertex_properties.end(),
165+
std::ranges::begin(properties_rng),
166+
std::ranges::end(properties_rng)
167+
);
180168
}
181169

182170
gl_attr_force_inline void remove_vertex(const id_type vertex_id) {
@@ -231,7 +219,7 @@ class graph final {
231219
[[nodiscard]] gl_attr_force_inline vertex_type vertex_unchecked(const id_type vertex_id
232220
) const noexcept {
233221
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
234-
return vertex_descriptor{vertex_id, *this->_vertex_properties[vertex_id]};
222+
return vertex_descriptor{vertex_id, this->_vertex_properties[vertex_id]};
235223
else
236224
return vertex_descriptor{vertex_id};
237225
}
@@ -241,21 +229,8 @@ class graph final {
241229
return this->vertex_unchecked(vertex_id);
242230
}
243231

244-
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept
245-
requires(traits::c_empty_properties<vertex_properties_type>)
246-
{
247-
return this->vertex_ids()
248-
| std::views::transform([](const id_type id) { return vertex_descriptor{id}; });
249-
}
250-
251-
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept
252-
requires(traits::c_non_empty_properties<vertex_properties_type>)
253-
{
254-
return this->_vertex_properties | std::views::enumerate
255-
| std::views::transform([](const auto& x) {
256-
const auto& [id, ptr] = x;
257-
return vertex_descriptor{static_cast<id_type>(id), *ptr};
258-
});
232+
[[nodiscard]] gl_attr_force_inline auto vertices() const noexcept {
233+
return this->vertex_ids() | std::views::transform(this->_create_vertex_descriptor());
259234
}
260235

261236
[[nodiscard]] gl_attr_force_inline auto vertex_ids() const noexcept {
@@ -264,7 +239,7 @@ class graph final {
264239

265240
[[nodiscard]] gl_attr_force_inline auto neighbors(const id_type vertex_id) const {
266241
return this->neighbor_ids(vertex_id)
267-
| std::views::transform([this](const id_type id) { return this->vertex(id); });
242+
| std::views::transform(this->_create_vertex_descriptor());
268243
}
269244

270245
[[nodiscard]] gl_attr_force_inline auto neighbors(vertex_type vertex) const {
@@ -282,7 +257,7 @@ class graph final {
282257

283258
[[nodiscard]] gl_attr_force_inline auto predecessors(const id_type vertex_id) const {
284259
return this->predecessor_ids(vertex_id)
285-
| std::views::transform([this](const id_type id) { return this->vertex(id); });
260+
| std::views::transform(this->_create_vertex_descriptor());
286261
}
287262

288263
[[nodiscard]] gl_attr_force_inline auto predecessors(vertex_type vertex) const {
@@ -300,7 +275,7 @@ class graph final {
300275

301276
[[nodiscard]] gl_attr_force_inline auto successors(const id_type vertex_id) const {
302277
return this->successor_ids(vertex_id)
303-
| std::views::transform([this](const id_type id) { return this->vertex(id); });
278+
| std::views::transform(this->_create_vertex_descriptor());
304279
}
305280

306281
[[nodiscard]] gl_attr_force_inline auto successors(vertex_type vertex) const {
@@ -321,13 +296,13 @@ class graph final {
321296
requires(traits::c_non_empty_properties<vertex_properties_type>)
322297
{
323298
this->_verify_vertex_id(id);
324-
return *this->_vertex_properties[id];
299+
return this->_vertex_properties[id];
325300
}
326301

327302
[[nodiscard]] gl_attr_force_inline auto vertex_properties_map() const noexcept
328303
requires(traits::c_non_empty_properties<vertex_properties_type>)
329304
{
330-
return util::deref_view(this->_vertex_properties);
305+
return std::views::all(this->_vertex_properties);
331306
}
332307

333308
// --- degree getters ---
@@ -635,7 +610,7 @@ class graph final {
635610
return false;
636611

637612
if constexpr (traits::c_non_empty_properties<vertex_properties_type>)
638-
if (not std::ranges::equal(lhs._vertex_properties, rhs._vertex_properties, val_eq))
613+
if (lhs._vertex_properties != rhs._vertex_properties)
639614
return false;
640615

641616
if constexpr (traits::c_non_empty_properties<edge_properties_type>)
@@ -678,16 +653,10 @@ class graph final {
678653
using fmt_traits = io::detail::graph_fmt_traits<directional_tag>;
679654

680655
graph(const graph& other)
681-
: _n_vertices{other._n_vertices}, _n_edges{other._n_edges}, _impl{other._impl} {
682-
// Deep copy vertex properties
683-
if constexpr (traits::c_non_empty_properties<vertex_properties_type>) {
684-
this->_vertex_properties.reserve(other._vertex_properties.size());
685-
for (const auto& property : other._vertex_properties)
686-
this->_vertex_properties.push_back(
687-
std::make_unique<vertex_properties_type>(*property)
688-
);
689-
}
690-
656+
: _n_vertices{other._n_vertices},
657+
_n_edges{other._n_edges},
658+
_impl{other._impl},
659+
_vertex_properties{other._vertex_properties} {
691660
// Deep copy edge properties
692661
if constexpr (traits::c_non_empty_properties<edge_properties_type>) {
693662
this->_edge_properties.reserve(other._edge_properties.size());
@@ -731,6 +700,22 @@ class graph final {
731700
}
732701
}
733702

703+
// --- transformations ---
704+
705+
gl_attr_force_inline auto _create_vertex_descriptor() const noexcept
706+
requires(traits::c_empty_properties<vertex_properties_type>)
707+
{
708+
return [](const id_type id) { return vertex_type{id}; };
709+
}
710+
711+
gl_attr_force_inline auto _create_vertex_descriptor() const noexcept
712+
requires(traits::c_non_empty_properties<vertex_properties_type>)
713+
{
714+
return [&pmap = this->_vertex_properties](const id_type id) {
715+
return vertex_type{id, pmap[to_idx(id)]};
716+
};
717+
}
718+
734719
// --- I/O utility ---
735720

736721
struct concise_target_formatter {
@@ -898,13 +883,16 @@ class graph final {
898883
return is;
899884
}
900885

886+
// --- data members ---
887+
901888
size_type _n_vertices = 0uz;
902889
size_type _n_edges = 0uz;
903890

904-
[[no_unique_address]] vertex_properties_map_type _vertex_properties{};
905-
[[no_unique_address]] edge_properties_map_type _edge_properties{};
906-
907891
implementation_type _impl{};
892+
893+
/// @todo Replace mutability with proper const-correct getter overloads to ensure thread safety guarantees associated with the const qualifier
894+
[[no_unique_address]] mutable vertex_properties_map_type _vertex_properties{};
895+
[[no_unique_address]] edge_properties_map_type _edge_properties{};
908896
};
909897

910898
// --- general graph utility ---

0 commit comments

Comments
 (0)