Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Replace parts of boost::optional with std::optional (#6551,… #6593

Closed
wants to merge 13 commits into from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- NodeJS:
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
- Misc:
- FIXED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551), see also [#6592](https://github.com/Project-OSRM/osrm-backend/issues/6592)
- CHANGED: Move vector in CSVFilesParser instead copying it. [#6470](https://github.com/Project-OSRM/osrm-backend/pull/6470)
- REMOVED: Get rid of unused functions in util/json_util.hpp. [#6446](https://github.com/Project-OSRM/osrm-backend/pull/6446)
- FIXED: Apply workaround for Conan installation issue on CI. [#6442](https://github.com/Project-OSRM/osrm-backend/pull/6442)
Expand Down
6 changes: 3 additions & 3 deletions include/engine/routing_algorithms/routing_base_ch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ bool stallAtNode(const DataFacade<Algorithm> &facade,
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT_MSG(edge_weight > EdgeWeight{0}, "edge_weight invalid");
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
if (toHeapNode)
{
if (toHeapNode->weight + edge_weight < heapNode.weight)
Expand Down Expand Up @@ -56,7 +56,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
BOOST_ASSERT_MSG(edge_weight > EdgeWeight{0}, "edge_weight invalid");
const EdgeWeight to_weight = heapNode.weight + edge_weight;

const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
// New Node discovered -> Add to Heap + Node Info Storage
if (!toHeapNode)
{
Expand All @@ -67,7 +67,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
{
// new parent
toHeapNode->data.parent = heapNode.node;
toHeapNode->weight = to_weight;
toHeapNode.value().weight = to_weight;
heap.DecreaseKey(*toHeapNode);
}
}
Expand Down
16 changes: 8 additions & 8 deletions include/engine/routing_algorithms/routing_base_mld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
{
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
BOOST_ASSERT(to_weight >= heapNode.weight);
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
if (!toHeapNode)
{
forward_heap.Insert(to, to_weight, {heapNode.node, true});
Expand All @@ -300,7 +300,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
{
toHeapNode->data = {heapNode.node, true};
toHeapNode->weight = to_weight;
forward_heap.DecreaseKey(*toHeapNode);
forward_heap.DecreaseKey(heapNode);
}
}
++destination;
Expand All @@ -321,7 +321,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
{
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
BOOST_ASSERT(to_weight >= heapNode.weight);
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
if (!toHeapNode)
{
forward_heap.Insert(to, to_weight, {heapNode.node, true});
Expand Down Expand Up @@ -360,16 +360,16 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const EdgeWeight to_weight =
heapNode.weight + node_weight + alias_cast<EdgeWeight>(turn_penalty);

const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
if (!toHeapNode)
{
forward_heap.Insert(to, to_weight, {heapNode.node, false});
}
else if (to_weight < toHeapNode->weight)
else if (to_weight < toHeapNode.value().weight)
{
toHeapNode->data = {heapNode.node, false};
toHeapNode->weight = to_weight;
forward_heap.DecreaseKey(*toHeapNode);
toHeapNode.value().data = {heapNode.node, false};
toHeapNode.value().weight = to_weight;
forward_heap.DecreaseKey(toHeapNode.value());
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions include/guidance/intersection_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@

#include <algorithm>
#include <cstddef>
#include <optional>
#include <utility>
#include <vector>

#include <boost/optional.hpp>

namespace osrm::guidance
{

Expand Down Expand Up @@ -129,7 +128,7 @@ class IntersectionHandler
// ^ via
//
// For this scenario returns intersection at `b` and `b`.
boost::optional<IntersectionHandler::IntersectionViewAndNode>
std::optional<IntersectionHandler::IntersectionViewAndNode>
getNextIntersection(const NodeID at, const EdgeID via) const;

bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const;
Expand Down
9 changes: 4 additions & 5 deletions include/guidance/sliproad_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@

#include "util/node_based_graph.hpp"

#include <optional>
#include <vector>

#include <boost/optional.hpp>

namespace osrm::guidance
{

Expand Down Expand Up @@ -43,9 +42,9 @@ class SliproadHandler final : public IntersectionHandler
Intersection intersection) const override final;

private:
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;
std::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;

// Next intersection from `start` onto `onto` is too far away for a Siproad scenario
bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const;
Expand Down
7 changes: 3 additions & 4 deletions include/guidance/turn_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp"

#include <boost/optional.hpp>

#include <cstddef>
#include <optional>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -72,7 +71,7 @@ class TurnHandler final : public IntersectionHandler

bool hasObvious(const EdgeID &via_edge, const Fork &fork) const;

boost::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
std::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;

bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const;

Expand All @@ -96,7 +95,7 @@ class TurnHandler final : public IntersectionHandler
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;

// Classification
boost::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
std::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;

OSRM_ATTR_WARN_UNUSED
Intersection assignLeftTurns(const EdgeID via_edge,
Expand Down
8 changes: 4 additions & 4 deletions include/nodejs/node_osrm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
#include <napi.h>

#include <boost/assert.hpp>
#include <boost/optional.hpp>

#include <algorithm>
#include <iostream>
#include <iterator>
#include <optional>
#include <sstream>
#include <stdexcept>
#include <string>
Expand Down Expand Up @@ -345,11 +345,11 @@ inline engine_config_ptr argumentsToEngineConfig(const Napi::CallbackInfo &args)
return engine_config;
}

inline boost::optional<std::vector<osrm::Coordinate>>
inline std::optional<std::vector<osrm::Coordinate>>
parseCoordinateArray(const Napi::Array &coordinates_array)
{
Napi::HandleScope scope(coordinates_array.Env());
boost::optional<std::vector<osrm::Coordinate>> resulting_coordinates;
std::optional<std::vector<osrm::Coordinate>> resulting_coordinates;
std::vector<osrm::Coordinate> temp_coordinates;

for (uint32_t i = 0; i < coordinates_array.Length(); ++i)
Expand Down Expand Up @@ -968,7 +968,7 @@ inline bool parseCommonParameters(const Napi::Object &obj, ParamType &params)

inline PluginParameters argumentsToPluginParameters(
const Napi::CallbackInfo &args,
const boost::optional<osrm::engine::api::BaseParameters::OutputFormatType> &output_format = {})
const std::optional<osrm::engine::api::BaseParameters::OutputFormatType> &output_format = {})
{
if (args.Length() < 3 || !args[1].IsObject())
{
Expand Down
8 changes: 4 additions & 4 deletions include/util/coordinate_calculation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
#include "util/coordinate.hpp"

#include <boost/math/constants/constants.hpp>
#include <boost/optional.hpp>

#include <algorithm>
#include <cmath>
#include <numeric>
#include <optional>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -102,9 +102,9 @@ double bearing(const Coordinate first_coordinate, const Coordinate second_coordi
double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third);

// find the center of a circle through three coordinates
boost::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
std::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);

// find the radius of a circle through three coordinates
double circleRadius(const Coordinate first_coordinate,
Expand Down
11 changes: 5 additions & 6 deletions include/util/geojson_debug_policies.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef OSRM_GEOJSON_DEBUG_POLICIES
#define OSRM_GEOJSON_DEBUG_POLICIES

#include <optional>
#include <vector>

#include "extractor/query_node.hpp"
Expand All @@ -9,8 +10,6 @@
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"

#include <boost/optional.hpp>

namespace osrm::util
{

Expand All @@ -20,7 +19,7 @@ struct NodeIdVectorToLineString

// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;

const std::vector<util::Coordinate> &node_coordinates;
};
Expand All @@ -29,7 +28,7 @@ struct CoordinateVectorToLineString
{
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
};

struct NodeIdVectorToMultiPoint
Expand All @@ -38,7 +37,7 @@ struct NodeIdVectorToMultiPoint

// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;

const std::vector<util::Coordinate> &node_coordinates;
};
Expand All @@ -47,7 +46,7 @@ struct CoordinateVectorToMultiPoint
{
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
};

} // namespace osrm::util
Expand Down
5 changes: 2 additions & 3 deletions include/util/geojson_debug_policy_toolkit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

#include <algorithm>
#include <iterator>

#include <boost/optional.hpp>
#include <optional>

namespace osrm::util
{
Expand Down Expand Up @@ -84,7 +83,7 @@ struct NodeIdToCoordinate

inline util::json::Object makeFeature(std::string type,
util::json::Array coordinates,
const boost::optional<util::json::Object> &properties = {})
const std::optional<util::json::Object> &properties = {})
{
util::json::Object result;
result.values["type"] = "Feature";
Expand Down
10 changes: 5 additions & 5 deletions include/util/query_heap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

#include <boost/assert.hpp>
#include <boost/heap/d_ary_heap.hpp>
#include <boost/optional.hpp>

#include <algorithm>
#include <limits>
#include <map>
#include <optional>
#include <unordered_map>
#include <vector>

Expand Down Expand Up @@ -289,7 +289,7 @@ class QueryHeap
return inserted_nodes[index].node == node;
}

boost::optional<HeapNode &> GetHeapNodeIfWasInserted(const NodeID node)
std::optional<HeapNode> GetHeapNodeIfWasInserted(NodeID node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I.e. now on each call we will copy HeapNode, right? How do we know that it won’t impact performance? May be worth refactoring it to HeapNode* instead(I mean use just pointer instead of optional here)? From some perspective optional<T&> is just overcomplicated way to express simple pointer…

WDYT?

P.S. I didn’t have a time yet to look over the rest of PR, just something important what I noticed…

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More than it: here you can see an example when we change contents of node in a heap and that by reference…

toHeapNode->data = {heapNode.node, true};

I.e. if we return it not by reference now most likely existing logic is broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did run my build and it did at least not segfault or got killed by kernel for too much RAM.
To cite from cppreference.com:
"There are no optional references; a program is ill-formed if it instantiates an optional with a reference type."
Search engine would suggest std::reference_wrapper for this task.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the same time as I can see if we just change it to simple pointer instead of optional(I.e. won’t use neither boost::optional nor std::optional) the rest of code which uses this QueryHeap would “just work” without changes we had to make there…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the other comment std::optional defines an operator->. However in some cases you probably would need to change a deref etc. I'm just testing solely using pointers for these parts. Does not work out of the box, but the idea should be doable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boost::optional<T&> seems to be effectively the same as T*, isn’t it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is. Still forking the main branch I need replace some of the idioms. Do you prefer nullptr or some void coercion ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is void coercion? You mean if (ptr == nullptr) vs if (!ptr)? Personally I like first option as more explicit, but I don’t think it would be blocker to merge this PR :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it's dreadfully simple, memory safety should be fine since it tests. I got too fed up with the nullptr version.
I think you need to approve CI again.

{
const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
Expand All @@ -300,7 +300,7 @@ class QueryHeap
return inserted_nodes[index];
}

boost::optional<const HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) const
std::optional<HeapNode> GetHeapNodeIfWasInserted(const NodeID node) const
{
const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
Expand Down Expand Up @@ -356,13 +356,13 @@ class QueryHeap
const auto index = node_index.peek_index(node);
auto &reference = inserted_nodes[index];
reference.weight = weight;
heap.increase(reference.handle, std::make_pair(weight, index));
heap.decrease(reference.handle, std::make_pair(weight, index));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is pretty fundamental to how the whole routing algorithm works. Can you explain exactly why this change is being made here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous link posted above:
https://www.boost.org/doc/libs/1_76_0/doc/html/boost/heap/d_ary_heap.html#id-1_3_18_6_2_1_1_1_22_17-bb
My thoughts behind this are that there is logic in multiple files e.g. include/engine/routing_algorithms/routing_base_mld.hpp that checks for a certain "to_weight" to be smaller than the current "toHeapNode->weight" and then calls DecreaseKey which in turn calls heap.increase with "to_weight".
So the docs say: "The new value is expected to be less than the current one" for decrease not increase.
Also I guess it kinda fixed a segfault for me while testing. (I know for sure it was this one, however might only have emerged with now reverted changes since now not using std::optional instead just pointers)
Am I completely mistaken here ? I still get from A to B though using my setup e.g. with the Germany map.

}

void DecreaseKey(const HeapNode &heapNode)
{
BOOST_ASSERT(!WasRemoved(heapNode.node));
heap.increase(heapNode.handle, std::make_pair(heapNode.weight, (*heapNode.handle).second));
heap.decrease(heapNode.handle, std::make_pair(heapNode.weight, (*heapNode.handle).second));
}

private:
Expand Down
4 changes: 3 additions & 1 deletion include/util/range_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
unsigned last_length = 0;
unsigned lengths_prefix_sum = 0;
unsigned block_idx = 0;
unsigned block_counter = 0;
BlockT block;
#ifndef BOOST_ASSERT_IS_VOID
unsigned block_counter = 0;
Copy link
Member

@danpat danpat Apr 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were merged to master in another PR #6596 - they should not also be showing up in this PR. I suspect some merges have been incorrectly applied or lost on the branch. This is probably also why CI is failing. I suspect if you tidy this up, CI should pass.

Copy link
Contributor

@AlTimofeyev AlTimofeyev Apr 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source code on master branch has block_counter = 0 on line 85, meanwhile in this commit it is placed on line 84. Could that be what's causing CI to fail?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mugr1x may be try to squash all your commits into single one? Or open another PR? Tbh for me it is not clear why it is happening - looks more like some GH bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlTimofeyev Well yes. Idk that much about CI.
@SiarheiFedartsou I did so #6611. Should I close this one ?
I also tried to rewrite some parsers. Point here is that the ones that are easy to rewrite work fine with switching to std::optional but the /server core API (and /engine because it there are crosslinks) don't.
I think this would be considered a too breaking change (at least ~1k lines of code) of new parser-related code.
Do you think there is value in #6592 or should I close this too ?
Also off-topic, but did you receive my email regarding GSoC. I was asking for what you mentors would expect. (I submitted my second version a bit late, though in time. Hope that is not a problem.)

unsigned block_sum = 0;
#endif
for (const unsigned l : lengths)
Expand Down Expand Up @@ -109,7 +109,9 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
if (BLOCK_SIZE == block_idx)
{
diff_blocks.push_back(block);
#ifndef BOOST_ASSERT_IS_VOID
block_counter++;
#endif
}

// we can only store strings with length 255
Expand Down
4 changes: 2 additions & 2 deletions include/util/timezones.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
#include <boost/filesystem/path.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/optional.hpp>

#include <rapidjson/document.h>

#include <chrono>
#include <optional>

namespace osrm::updater
{
Expand All @@ -34,7 +34,7 @@ class Timezoner
Timezoner(const char geojson[], std::time_t utc_time_now);
Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now);

boost::optional<struct tm> operator()(const point_t &point) const;
std::optional<struct tm> operator()(const point_t &point) const;

private:
void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time);
Expand Down
2 changes: 1 addition & 1 deletion src/contractor/contractor_search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void relaxNode(ContractorHeap &heap,
}
const EdgeWeight to_weight = node_weight + data.weight;

const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
// New Node discovered -> Add to Heap + Node Info Storage
if (!toHeapNode)
{
Expand Down
Loading