Program Listing for File LocatorSelector.hpp
↰ Return to documentation for file (/tmp/ws/src/fastrtps/include/fastdds/rtps/common/LocatorSelector.hpp
)
// Copyright 2019 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_RTPS_COMMON_LOCATORSELECTOR_HPP_
#define _FASTDDS_RTPS_COMMON_LOCATORSELECTOR_HPP_
#include <fastdds/rtps/common/LocatorSelectorEntry.hpp>
#include <fastdds/rtps/common/Guid.h>
#include <fastdds/rtps/common/Locator.h>
#include <fastrtps/utils/collections/ResourceLimitedVector.hpp>
#include <fastrtps/utils/IPLocator.h>
#include <algorithm>
namespace eprosima {
namespace fastrtps {
namespace rtps {
class LocatorSelector
{
public:
LocatorSelector(
const ResourceLimitedContainerConfig& entries_allocation)
: entries_(entries_allocation)
, selections_(entries_allocation)
, last_state_(entries_allocation)
{
}
void clear()
{
entries_.clear();
selections_.clear();
last_state_.clear();
}
bool add_entry(
LocatorSelectorEntry* entry)
{
return entries_.push_back(entry) != nullptr;
}
bool remove_entry(
const GUID_t& guid)
{
return entries_.remove_if(
[&guid](LocatorSelectorEntry* entry)
{
return entry->remote_guid == guid;
});
}
void reset(
bool enable_all)
{
last_state_.clear();
for (LocatorSelectorEntry* entry : entries_)
{
last_state_.push_back(entry->enabled ? 1 : 0);
entry->enable(enable_all);
}
}
void enable(
const GUID_t& guid)
{
for (LocatorSelectorEntry* entry : entries_)
{
if (entry->remote_guid == guid)
{
entry->enabled = true;
break;
}
}
}
bool state_has_changed() const
{
if (entries_.size() != last_state_.size())
{
return true;
}
for (size_t i = 0; i < entries_.size(); ++i)
{
if (last_state_.at(i) != (entries_.at(i)->enabled ? 1 : 0))
{
return true;
}
}
return false;
}
void selection_start()
{
selections_.clear();
for (LocatorSelectorEntry* entry : entries_)
{
entry->reset();
}
}
ResourceLimitedVector<LocatorSelectorEntry*>& transport_starts()
{
for (LocatorSelectorEntry* entry : entries_)
{
entry->transport_should_process = entry->enabled;
}
return entries_;
}
void select(
size_t index)
{
if (index < entries_.size() &&
std::find(selections_.begin(), selections_.end(), index) == selections_.end())
{
selections_.push_back(index);
}
}
size_t selected_size() const
{
size_t result = 0;
for (size_t index : selections_)
{
LocatorSelectorEntry* entry = entries_.at(index);
result += entry->state.multicast.size();
result += entry->state.unicast.size();
}
return result;
}
bool is_selected(
const Locator_t locator) const
{
if (IPLocator::isMulticast(locator))
{
for (size_t index : selections_)
{
LocatorSelectorEntry* entry = entries_.at(index);
for (size_t loc_index : entry->state.multicast)
{
if (entry->multicast.at(loc_index) == locator)
{
return true;
}
}
}
}
else
{
for (size_t index : selections_)
{
LocatorSelectorEntry* entry = entries_.at(index);
for (size_t loc_index : entry->state.unicast)
{
if (entry->unicast.at(loc_index) == locator)
{
return true;
}
}
}
}
return false;
}
template<class UnaryPredicate>
void for_each(
UnaryPredicate action) const
{
for (size_t index : selections_)
{
LocatorSelectorEntry* entry = entries_.at(index);
for (size_t loc_index : entry->state.multicast)
{
action(entry->multicast.at(loc_index));
}
for (size_t loc_index : entry->state.unicast)
{
action(entry->unicast.at(loc_index));
}
}
}
struct IteratorIndex
{
size_t selections_index;
size_t state_index;
bool state_multicast_done;
Locator_t* locator;
};
class iterator :
public LocatorsIterator
{
// use of std::iterator to introduce the following aliases is deprecated
using iterator_category = std::input_iterator_tag;
using value_type = Locator_t;
using difference_type = IteratorIndex;
using pointer = Locator_t*;
using reference = Locator_t&;
const LocatorSelector& locator_selector_;
IteratorIndex current_;
void go_to_next_entry()
{
// While entries selected
while (++current_.selections_index < locator_selector_.selections_.size())
{
LocatorSelectorEntry* entry =
locator_selector_.entries_.at(locator_selector_.selections_[current_.selections_index]);
// No multicast locators in this entry
if (entry->state.multicast.size() == 0)
{
// But there's unicast
if (entry->state.unicast.size() > 0)
{
current_.locator = &entry->unicast[entry->state.unicast.at(0)];
return;
}
}
else // process multicast
{
current_.state_multicast_done = false;
current_.locator = &entry->multicast[entry->state.multicast.at(0)];
return;
}
}
current_.locator = nullptr;
}
public:
enum class Position
{
Begin,
End
};
explicit iterator(
const LocatorSelector& locator_selector,
Position index_pos)
: locator_selector_(locator_selector)
{
current_ = {(std::numeric_limits<size_t>::max)(), 0, true, nullptr};
if (index_pos == Position::Begin)
{
go_to_next_entry();
}
}
iterator(
const iterator& other)
: locator_selector_(other.locator_selector_)
, current_(other.current_)
{
}
iterator& operator ++()
{
// Shouldn't call ++ when index already at the end
assert(current_.selections_index < locator_selector_.selections_.size());
LocatorSelectorEntry* entry =
locator_selector_.entries_.at(locator_selector_.selections_[current_.selections_index]);
// Index at unicast locators
if (current_.state_multicast_done)
{
// No more unicast locators selected
if (++current_.state_index >= entry->state.unicast.size())
{
current_.state_index = 0;
go_to_next_entry();
}
else // current unicast locator
{
current_.locator = &entry->unicast[entry->state.unicast.at(current_.state_index)];
}
}
else // Index at multicast locators
{
// No more multicast locators selected
if (++current_.state_index >= entry->state.multicast.size())
{
// Reset index to process unicast
current_.state_multicast_done = true;
current_.state_index = 0;
// No unicast locators
if (current_.state_index >= entry->state.unicast.size())
{
go_to_next_entry();
}
else // current unicast locator
{
current_.locator = &entry->unicast[entry->state.unicast.at(current_.state_index)];
}
}
else // current multicast locator
{
current_.locator = &entry->multicast[entry->state.multicast.at(current_.state_index)];
}
}
return *this;
}
bool operator ==(
const LocatorsIterator& other) const
{
return *this == static_cast<const iterator&>(other);
}
bool operator !=(
const LocatorsIterator& other) const
{
return !(*this == other);
}
bool operator ==(
const iterator& other) const
{
return (current_.locator == other.current_.locator);
}
bool operator !=(
const iterator& other) const
{
return !(*this == other);
}
pointer operator ->() const
{
return current_.locator;
}
reference operator *() const
{
return *current_.locator;
}
};
iterator begin() const
{
return iterator(*this, iterator::Position::Begin);
}
iterator end() const
{
return iterator(*this, iterator::Position::End);
}
private:
ResourceLimitedVector<LocatorSelectorEntry*> entries_;
ResourceLimitedVector<size_t> selections_;
ResourceLimitedVector<int> last_state_;
};
} /* namespace rtps */
} /* namespace fastrtps */
} /* namespace eprosima */
#endif /* _FASTDDS_RTPS_COMMON_LOCATORSELECTOR_H_ */