Skip to content

Commit

Permalink
Use Boost ICL for RangeSet (RIPD-1473)
Browse files Browse the repository at this point in the history
  • Loading branch information
bachase committed May 18, 2017
1 parent 24e1b99 commit 4b00186
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 497 deletions.
4 changes: 0 additions & 4 deletions Builds/VisualStudio2015/RippleD.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1431,10 +1431,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\RangeSet.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\ResolverAsio.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
Expand Down
3 changes: 0 additions & 3 deletions Builds/VisualStudio2015/RippleD.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -1959,9 +1959,6 @@
<ClCompile Include="..\..\src\ripple\basics\impl\mulDiv.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\RangeSet.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\basics\impl\ResolverAsio.cpp">
<Filter>ripple\basics\impl</Filter>
</ClCompile>
Expand Down
2 changes: 1 addition & 1 deletion src/ripple/app/ledger/LedgerMaster.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class LedgerMaster
std::unique_ptr<LedgerReplay> replayData;

std::recursive_mutex mCompleteLock;
RangeSet mCompleteLedgers;
RangeSet<std::uint32_t> mCompleteLedgers;

std::unique_ptr <detail::LedgerCleaner> mLedgerCleaner;

Expand Down
242 changes: 115 additions & 127 deletions src/ripple/app/ledger/impl/LedgerMaster.cpp

Large diffs are not rendered by default.

133 changes: 87 additions & 46 deletions src/ripple/basics/RangeSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,72 +20,113 @@
#ifndef RIPPLE_BASICS_RANGESET_H_INCLUDED
#define RIPPLE_BASICS_RANGESET_H_INCLUDED

#include <cstdint>
#include <map>
#include <string>
#include <boost/optional.hpp>
#include <boost/icl/closed_interval.hpp>
#include <boost/icl/interval_set.hpp>

namespace ripple {

/** A sparse set of integers. */
// VFALCO TODO Replace with juce::SparseSet
class RangeSet
namespace ripple
{
public:
static const std::uint32_t absent = static_cast <std::uint32_t> (-1);

public:
RangeSet () { }
/** A closed interval over the domain T.
bool hasValue (std::uint32_t) const;
For an instance ClosedInterval c, this represents the closed interval
(c.first(), c.last()). A single element interval has c.first() == c.last().
std::uint32_t getFirst () const;
std::uint32_t getNext (std::uint32_t) const;
std::uint32_t getLast () const;
std::uint32_t getPrev (std::uint32_t) const;
This is simply a type-alias for boost interval container library interval
set, so users should consult that documentation for available supporting
member and free functions.
*/
template <class T>
using ClosedInterval = boost::icl::closed_interval<T>;

// largest number not in the set that is less than the given number
std::uint32_t prevMissing (std::uint32_t) const;
/** Create a closed range interval
// Add an item to the set
void setValue (std::uint32_t);
Helper function to create a closed range interval without having to qualify
the template argument.
*/
template <class T>
ClosedInterval<T>
range(T low, T high)
{
return ClosedInterval<T>(low, high);
}

// Add the closed interval to the set
void setRange (std::uint32_t, std::uint32_t);
/** A set of closed intervals over the domain T.
void clearValue (std::uint32_t);
Represents a set of values of the domain T using the minimum number
of disjoint ClosedInterval<T>. This is useful to represent ranges of
T where a few instances are missing, e.g. the set 1-5,8-9,11-14.
std::string toString () const;
This is simply a type-alias for boost interval container library interval
set, so users should consult that documentation for available supporting
member and free functions.
*/
template <class T>
using RangeSet = boost::icl::interval_set<T, std::less, ClosedInterval<T>>;

/** Returns the sum of the Lebesgue measures of all sub-ranges. */
std::size_t
lebesgue_sum() const;

/** Check invariants of the data.
/** Convert a ClosedInterval to a styled string
This is for diagnostics, and does nothing in release builds.
*/
void checkInternalConsistency () const noexcept;
The styled string is
"c.first()-c.last()" if c.first() != c.last()
"c.first()" if c.first() == c.last()
private:
void simplify ();
@param ci The closed interval to convert
@return The style string
*/
template <class T>
std::string to_string(ClosedInterval<T> const & ci)
{
if (ci.first() == ci.last())
return std::to_string(ci.first());
return std::to_string(ci.first()) + "-" + std::to_string(ci.last());
}

private:
using Map = std::map <std::uint32_t, std::uint32_t>;
/** Convert the given RangeSet to a styled string.
using const_iterator = Map::const_iterator;
using const_reverse_iterator = Map::const_reverse_iterator;
using value_type = Map::value_type;
using iterator = Map::iterator;
The styled string represention is the set of disjoint intervals joined by
commas. The string "empty" is returned if the set is empty.
static bool contains (value_type const& it, std::uint32_t v)
@param rs The rangeset to convert
@return The styled string
*/
template <class T>
std::string to_string(RangeSet<T> const & rs)
{
using ripple::to_string;

if (rs.empty())
return "empty";
std::string res = "";
for (auto const & interval : rs)
{
return (it.first <= v) && (it.second >= v);
if (!res.empty())
res += ",";
res += to_string(interval);
}
return res;
}

// First is lowest value in range, last is highest value in range
Map mRanges;
};

} // ripple
/** Find the largest value not in the set that is less than a given value.
@param rs The set of interest
@param t The value that must be larger than the result
@param minVal (Default is 0) The smallest allowed value
@return The largest v such that minV <= v < t and !contains(rs, v) or
boost::none if no such v exists.
*/
template <class T>
boost::optional<T>
prevMissing(RangeSet<T> const & rs, T t, T minVal = 0)
{
if (rs.empty() || t == minVal)
return boost::none;
RangeSet<T> tgt{ ClosedInterval<T>{minVal, t - 1} };
tgt -= rs;
if (tgt.empty())
return boost::none;
return boost::icl::last(tgt);
}
} // namespace ripple
#endif
Loading

0 comments on commit 4b00186

Please sign in to comment.