Program Listing for File LoanableSequence.hpp

Return to documentation for file (/tmp/ws/src/fastrtps/include/fastdds/dds/core/LoanableSequence.hpp)

// Copyright 2020 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_DDS_CORE_LOANABLESEQUENCE_HPP_
#define _FASTDDS_DDS_CORE_LOANABLESEQUENCE_HPP_

#include <cassert>
#include <cstdint>
#include <vector>
#include <type_traits>

#include <fastdds/dds/core/LoanableTypedCollection.hpp>
#include <fastdds/dds/log/Log.hpp>

namespace eprosima {
namespace fastdds {
namespace dds {

template<typename T, typename _NonConstEnabler = std::true_type>
class LoanableSequence : public LoanableTypedCollection<T, _NonConstEnabler>
{
public:

    using size_type = LoanableCollection::size_type;
    using element_type = LoanableCollection::element_type;

    LoanableSequence() = default;

    LoanableSequence(
            size_type max)
    {
        if (max <= 0)
        {
            return;
        }

        resize(max);
    }

    ~LoanableSequence()
    {
        if (elements_ && !has_ownership_)
        {
            EPROSIMA_LOG_WARNING(SUBSCRIBER, "Sequence destroyed with active loan");
            return;
        }

        release();
    }

    LoanableSequence(
            const LoanableSequence& other)
    {
        *this = other;
    }

    LoanableSequence& operator =(
            const LoanableSequence& other)
    {
        if (!has_ownership_)
        {
            release();
        }

        LoanableCollection::length(other.length());
        const element_type* other_buf = other.buffer();
        for (size_type n = 0; n < length_; ++n)
        {
            *static_cast<T*>(elements_[n]) = *static_cast<const T*>(other_buf[n]);
        }

        return *this;
    }

protected:

    using LoanableCollection::maximum_;
    using LoanableCollection::length_;
    using LoanableCollection::elements_;
    using LoanableCollection::has_ownership_;

private:

    void resize(
            size_type maximum) override
    {
        assert(has_ownership_);

        // Resize collection and get new pointer
        data_.reserve(maximum);
        data_.resize(maximum);
        elements_ = reinterpret_cast<element_type*>(data_.data());

        // Allocate individual elements
        while (maximum_ < maximum)
        {
            data_[maximum_++] = new T();
        }
    }

    void release()
    {
        if (has_ownership_ && elements_)
        {
            for (size_type n = 0; n < maximum_; ++n)
            {
                T* elem = data_[n];
                delete elem;
            }
            std::vector<T*>().swap(data_);
        }

        maximum_ = 0u;
        length_ = 0u;
        elements_ = nullptr;
        has_ownership_ = true;
    }

    std::vector<T*> data_;
};

} // namespace dds
} // namespace fastdds
} // namespace eprosima

// Macro to easily declare a LoanableSequence for a data type
#define FASTDDS_SEQUENCE(FooSeq, Foo) using FooSeq = eprosima::fastdds::dds::LoanableSequence<Foo>
#define FASTDDS_CONST_SEQUENCE(FooSeq, Foo) using FooSeq = eprosima::fastdds::dds::LoanableSequence<Foo, \
                    std::false_type>

#endif // _FASTDDS_DDS_CORE_LOANABLESEQUENCE_HPP_