Program Listing for File SequenceNumber.h

Return to documentation for file (/tmp/ws/src/fastrtps/include/fastdds/rtps/common/SequenceNumber.h)

// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _FASTDDS_RPTS_ELEM_SEQNUM_H_
#define _FASTDDS_RPTS_ELEM_SEQNUM_H_

#include <algorithm>
#include <cassert>
#include <limits>
#include <vector>

#include <fastrtps/fastrtps_dll.h>
#include <fastrtps/utils/fixed_size_bitmap.hpp>
#include <fastdds/rtps/common/Types.h>

namespace eprosima {
namespace fastrtps {
namespace rtps {


struct RTPS_DllAPI SequenceNumber_t
{
    int32_t high = 0;
    uint32_t low = 0;

    SequenceNumber_t() noexcept
    {
        high = 0;
        low = 0;
    }

    SequenceNumber_t(
            int32_t hi,
            uint32_t lo) noexcept
        : high(hi)
        , low(lo)
    {
    }

    explicit
    SequenceNumber_t(
            uint64_t u) noexcept
        : high(static_cast<int32_t>(u >> 32u))
        , low(static_cast<uint32_t>(u))
    {
    }

    uint64_t to64long() const noexcept
    {
        return (static_cast<uint64_t>(high) << 32u) + low;
    }

    SequenceNumber_t& operator ++() noexcept
    {
        ++low;
        if (low == 0)
        {
            assert(std::numeric_limits<decltype(high)>::max() > high);
            ++high;
        }

        return *this;
    }

    SequenceNumber_t operator ++(
            int) noexcept
    {
        SequenceNumber_t result(*this);
        ++(*this);
        return result;
    }

    SequenceNumber_t& operator +=(
            int inc) noexcept
    {
        assert(inc >= 0);
        uint32_t aux_low = low;
        low +=  static_cast<uint32_t>(inc);

        if (low < aux_low)
        {
            // Being the type of the parameter an 'int', the increment of 'high' will be as much as 1.
            assert(std::numeric_limits<decltype(high)>::max() > high);
            ++high;
        }

        return *this;
    }

    static SequenceNumber_t unknown() noexcept
    {
        return { -1, 0 };
    }

};

#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

inline bool operator ==(
        const SequenceNumber_t& sn1,
        const SequenceNumber_t& sn2) noexcept
{
    return (sn1.low == sn2.low) && (sn1.high == sn2.high);
}

inline bool operator !=(
        const SequenceNumber_t& sn1,
        const SequenceNumber_t& sn2) noexcept
{
    return (sn1.low != sn2.low) || (sn1.high != sn2.high);
}

inline bool operator >(
        const SequenceNumber_t& seq1,
        const SequenceNumber_t& seq2) noexcept
{
    if (seq1.high == seq2.high)
    {
        return seq1.low > seq2.low;
    }

    return seq1.high > seq2.high;
}

inline bool operator <(
        const SequenceNumber_t& seq1,
        const SequenceNumber_t& seq2) noexcept
{
    if (seq1.high == seq2.high)
    {
        return seq1.low < seq2.low;
    }

    return seq1.high < seq2.high;
}

inline bool operator >=(
        const SequenceNumber_t& seq1,
        const SequenceNumber_t& seq2) noexcept
{
    if (seq1.high == seq2.high)
    {
        return seq1.low >= seq2.low;
    }

    return seq1.high > seq2.high;
}

inline bool operator <=(
        const SequenceNumber_t& seq1,
        const SequenceNumber_t& seq2) noexcept
{
    if (seq1.high == seq2.high)
    {
        return seq1.low <= seq2.low;
    }

    return seq1.high < seq2.high;
}

inline SequenceNumber_t operator -(
        const SequenceNumber_t& seq,
        const uint32_t inc) noexcept
{
    SequenceNumber_t res(seq.high, seq.low - inc);

    if (inc > seq.low)
    {
        // Being the type of the parameter an 'uint32_t', the decrement of 'high' will be as much as 1.
        assert(0 < res.high);
        --res.high;
    }

    return res;
}

inline SequenceNumber_t operator +(
        const SequenceNumber_t& seq,
        const uint32_t inc) noexcept
{
    SequenceNumber_t res(seq.high, seq.low + inc);

    if (res.low < seq.low)
    {
        // Being the type of the parameter an 'uint32_t', the increment of 'high' will be as much as 1.
        assert(std::numeric_limits<decltype(res.high)>::max() > res.high);
        ++res.high;
    }

    return res;
}

inline SequenceNumber_t operator -(
        const SequenceNumber_t& minuend,
        const SequenceNumber_t& subtrahend) noexcept
{
    assert(minuend >= subtrahend);
    SequenceNumber_t res(minuend.high - subtrahend.high, minuend.low - subtrahend.low);

    if (minuend.low < subtrahend.low)
    {
        assert(0 < res.high);
        --res.high;
    }

    return res;
}

#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

const SequenceNumber_t c_SequenceNumber_Unknown{-1, 0};

#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

inline bool sort_seqNum(
        const SequenceNumber_t& s1,
        const SequenceNumber_t& s2) noexcept
{
    return s1 < s2;
}

inline std::ostream& operator <<(
        std::ostream& output,
        const SequenceNumber_t& seqNum)
{
    return output << seqNum.to64long();
}

inline std::ostream& operator <<(
        std::ostream& output,
        const std::vector<SequenceNumber_t>& seqNumSet)
{
    for (const SequenceNumber_t& sn : seqNumSet)
    {
        output << sn << " ";
    }

    return output;
}

struct SequenceNumberHash
{
    std::size_t operator ()(
            const SequenceNumber_t& sequence_number) const noexcept
    {
        return static_cast<std::size_t>(sequence_number.to64long());
    }

};

struct SequenceNumberDiff
{
    uint32_t operator ()(
            const SequenceNumber_t& a,
            const SequenceNumber_t& b) const noexcept
    {
        SequenceNumber_t diff = a - b;
        return diff.low;
    }

};

#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

using SequenceNumberSet_t = BitmapRange<SequenceNumber_t, SequenceNumberDiff, 256>;

#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

inline std::ostream& operator <<(
        std::ostream& output,
        const SequenceNumberSet_t& sns)
{
    output << sns.base().to64long() << ":";
    sns.for_each([&output](
                SequenceNumber_t it)
            {
                output << it.to64long() << "-";
            });

    return output;
}

inline std::istream& operator >>(
        std::istream& input,
        SequenceNumber_t& seqNum)
{
    uint64_t aux;

    if (input >> aux)
    {
        seqNum = SequenceNumber_t(aux);
    }

    return input;
}

#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

} // namespace rtps
} // namespace fastrtps
} // namespace eprosima

#endif /* _FASTDDS_RTPS_ELEM_SEQNUM_H_ */