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

Iox #221 apply cxx list #224

Merged

Conversation

bishibashiB
Copy link
Contributor

@bishibashiB bishibashiB commented Aug 7, 2020

Within the attached source std::list usage was removed from roudi process list handling (replaced with cxx::list implementation).
Additionally the FixedPositionContainer of roudi port pool was picked to replace with cxx::list as well... see details in #221. (fixes #221)

This PR requires cxx::list to be approved (merged) #215 first.

@mossmaurice mossmaurice added the enhancement New feature label Aug 14, 2020
@bishibashiB bishibashiB force-pushed the feature/iox-#221_apply_cxx_list branch 2 times, most recently from 2273d40 to b7f9475 Compare August 14, 2020 13:34
@@ -28,8 +28,8 @@ class IceOryxPortPool : public PortPool
public:
IceOryxPortPool(PortPoolData& portPool) noexcept;

cxx::vector<SenderPortType::MemberType_t*, MAX_PORT_NUMBER> senderPortDataList() noexcept override;
cxx::vector<ReceiverPortType::MemberType_t*, MAX_PORT_NUMBER> receiverPortDataList() noexcept override;
cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept override;
Copy link
Contributor

Choose a reason for hiding this comment

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

Uh this is dangerous. What if someone takes the list and modifies it arbitrarily? Is this what we want? If yes, then we can just make the whole list public, otherwise I would return here a copy.

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 your comment below (restructuring) ... #257

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy if efficiency is no concern, const& otherwise (depends who uses it, really). This does not protect against const_casts though but sends a strong message that it is read-only. If another API already requires modifying the list (i.e. we need a non const &) we need to take a further look.
Was a similar problem before with the vector, so I do not necessarily see it as in scope of this PR to fix this API design.

Copy link
Contributor

@MatthiasKillat MatthiasKillat Sep 18, 2020

Choose a reason for hiding this comment

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

A discussion lead to the following proposal: return a container (probably still a vector if it is just read from) of pointers to the ports as is instead of a reference to the underlying container, which is now a list.
This has more overhead since this container needs to be constructed every time the function is called (this was also the case before in the content() function), but does not expose the internal list (but the ports, as before).

In the long run this can maybe be improved even more by passing the list reference as proposed, at the cost of losing encapsulation (the implications need to be checked carefully).

The underlying container should still be changed to a list to allow efficient insertion and removal.

cxx::vector<popo::InterfacePortData*, MAX_INTERFACE_NUMBER> interfacePortDataList() noexcept;
cxx::vector<popo::ApplicationPortData*, MAX_PROCESS_NUMBER> appliactionPortDataList() noexcept;
cxx::vector<runtime::RunnableData*, MAX_RUNNABLE_NUMBER> runnableDataList() noexcept;
virtual cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, it is dangerous to return the reference to internal members. Then everyone can modify, delete and add anything they like - even invalid data. If this is what we want make the list public otherwise we have to return a copy 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 your comment below (restructuring via new issue) ... #257

Copy link
Contributor

Choose a reason for hiding this comment

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

Still depends on how it is used, sometimes breaking encapsulation for internal classes to acheive efficiency makes perfect sense. Regardless, the encapsulation was compromised before and ith is not necessarily in scope of this PR to fix this.

iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
{
auto interfacePortData = m_portPoolDataBase->m_interfacePortMembers.insert(
auto interfacePortData = &m_portPoolDataBase->m_interfacePortMembers.emplace_front(
iox::cxx::string<100>(iox::cxx::TruncateToCapacity, applicationName), interface);
Copy link
Contributor

Choose a reason for hiding this comment

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

No magic numbers. Why string<100>?
You could use the alias using ProcessName_t = cxx::string<100>; which can be found in iceoryx_posh_types.hpp

I know you did not write this particular line of code but the boyscout principle applies and you should always leave the code a little bit cleaner then you found 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.

I understand it is valuable to remove any of those magic numbers. I fully agree!
For sure I will do a round-about approach to remove those- my proposal: in a follow-up issue / PR #257 (as the change would not be about this single line...)
Additionally there is something about using a type 'ProcessName_t' for an 'applicationName' which sparks my naming convention senses.
As I guess there is room for discussion on the number of name-types-in-use for process, application, runnable, service I leave this for discussions before creating any other precedents.

iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
Copy link
Contributor Author

@bishibashiB bishibashiB left a comment

Choose a reason for hiding this comment

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

Addressed comments from @elfenpiff
Ether committed or forwarded to #257

@@ -25,27 +25,27 @@ PortPool::PortPool(PortPoolDataBase& portPoolDataBase) noexcept
{
}

cxx::vector<popo::InterfacePortData*, MAX_INTERFACE_NUMBER> PortPool::interfacePortDataList() noexcept
cxx::list<popo::InterfacePortData, MAX_INTERFACE_NUMBER>& PortPool::interfacePortDataList() noexcept
Copy link
Contributor Author

Choose a reason for hiding this comment

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

May I forward this point to a new issue? #257
I think we agree that copying a list is not in favour. So the interface between port_pool and roudi should be fostered.

iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_manager.cpp Outdated Show resolved Hide resolved
{
iox::popo::ApplicationPort applicationPort(applicationPortData);
auto checkIter = iter;
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 above...

iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
iceoryx_posh/source/roudi/port_pool.cpp Outdated Show resolved Hide resolved
cxx::vector<popo::InterfacePortData*, MAX_INTERFACE_NUMBER> interfacePortDataList() noexcept;
cxx::vector<popo::ApplicationPortData*, MAX_PROCESS_NUMBER> appliactionPortDataList() noexcept;
cxx::vector<runtime::RunnableData*, MAX_RUNNABLE_NUMBER> runnableDataList() noexcept;
virtual cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept = 0;
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 your comment below (restructuring via new issue) ... #257

@@ -28,8 +28,8 @@ class IceOryxPortPool : public PortPool
public:
IceOryxPortPool(PortPoolData& portPool) noexcept;

cxx::vector<SenderPortType::MemberType_t*, MAX_PORT_NUMBER> senderPortDataList() noexcept override;
cxx::vector<ReceiverPortType::MemberType_t*, MAX_PORT_NUMBER> receiverPortDataList() noexcept override;
cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept override;
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 your comment below (restructuring) ... #257

@@ -28,8 +28,8 @@ class IceOryxPortPool : public PortPool
public:
IceOryxPortPool(PortPoolData& portPool) noexcept;

cxx::vector<SenderPortType::MemberType_t*, MAX_PORT_NUMBER> senderPortDataList() noexcept override;
cxx::vector<ReceiverPortType::MemberType_t*, MAX_PORT_NUMBER> receiverPortDataList() noexcept override;
cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept override;
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy if efficiency is no concern, const& otherwise (depends who uses it, really). This does not protect against const_casts though but sends a strong message that it is read-only. If another API already requires modifying the list (i.e. we need a non const &) we need to take a further look.
Was a similar problem before with the vector, so I do not necessarily see it as in scope of this PR to fix this API design.

cxx::vector<popo::InterfacePortData*, MAX_INTERFACE_NUMBER> interfacePortDataList() noexcept;
cxx::vector<popo::ApplicationPortData*, MAX_PROCESS_NUMBER> appliactionPortDataList() noexcept;
cxx::vector<runtime::RunnableData*, MAX_RUNNABLE_NUMBER> runnableDataList() noexcept;
virtual cxx::list<SenderPortType::MemberType_t, MAX_PORT_NUMBER>& senderPortDataList() noexcept = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Still depends on how it is used, sometimes breaking encapsulation for internal classes to acheive efficiency makes perfect sense. Regardless, the encapsulation was compromised before and ith is not necessarily in scope of this PR to fix this.

@@ -75,8 +75,8 @@ class PortPool
const iox::cxx::CString100& runnable,
const uint64_t runnableDeviceIdentifier) noexcept;

virtual void removeSenderPort(SenderPortType::MemberType_t* const portData) noexcept = 0;
virtual void removeReceiverPort(ReceiverPortType::MemberType_t* const portData) noexcept = 0;
virtual void removeSenderPort(const SenderPortType::MemberType_t& portData) noexcept = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Apart from pointer to ref the semantics changed here as well, was a const pointer but mutable data before (which is not that useful in function arguments, same as passing a const int), now the data is immutable. The function seems not to modify it (i.e. it compiles), so it is Ok.
Just an observation that it is stricter now.

@@ -266,9 +266,9 @@ void SenderPort::deliverChunkToAllReceiver(const mepoo::SharedChunk f_chunk)

auto& receiverList = getMembers()->m_receiverHandler.appContext().getReceiverList();

for (int64_t i = static_cast<int64_t>(receiverList.size()) - 1; i >= 0; --i)
for (auto& receiver : receiverList)
Copy link
Contributor

Choose a reason for hiding this comment

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

Well, I guess the order was not important anyway (was reverse before, for whatever reason). It should only be important that it is delivered to every receiver, not in which order.

@@ -26,15 +26,15 @@ IceOryxPortPool::IceOryxPortPool(PortPoolData& portPoolData) noexcept
}

/// @deprecated #25
cxx::vector<SenderPortType::MemberType_t*, MAX_PUBLISHERS> IceOryxPortPool::senderPortDataList() noexcept
cxx::list<SenderPortType::MemberType_t, MAX_PUBLISHERS>& IceOryxPortPool::senderPortDataList() noexcept
Copy link
Contributor

Choose a reason for hiding this comment

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

Returning the container by reference now is intentional? (For efficiency?) Before we returned a container filled with pointers, now we return a reference to the container. The internal elements are exposed either way. This way the container is also exposed for modification (more misuse potential).

{
m_portPoolData->m_senderPortMembers.erase(portData);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, worked before because the iterators where pointers (for cxx::vector). Now to ensure deletion we need to provide a reference to an object actually in the container (equivalent to a pointer in this regard). Should be fine, but worth thinking about that it is still correct and equivalent to before. We cannot delete by id or name or anything else. The address of the object to be deleted is essentially the id.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We cannot delete by id or name or anything else. The address of the object to be deleted is essentially the id.

Q: Could there appear a race where the pointer-is-ID approach becomes corrupted due to different address ranges in processes... ?

@bishibashiB bishibashiB changed the title Feature/iox #221 apply cxx list Iox #221 apply cxx list Sep 16, 2020
@@ -53,7 +53,7 @@ class ReceiverHandler : public LockingPolicy
using this_type = ReceiverHandler_t;

public:
using ReceiverVector_t = cxx::vector<relative_ptr<ReceiverPortType::MemberType_t>, MaxReceivers>;
using ReceiverList_t = cxx::list<relative_ptr<ReceiverPortType::MemberType_t>, MaxReceivers>;
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if this is really a good replacement. While theoretically a list would be a good idea, this list is rarely changed, but often read and therefore it might be faster if it remains a vector, even if it means that removing items will be quite slow

Copy link
Contributor

Choose a reason for hiding this comment

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

You may be right here. Cache Locality is much worse with the list and this is probably the reason for a large performance loss while iterating over its elements.

@mossmaurice mossmaurice added this to the v1.x milestone Nov 4, 2020
Signed-off-by: Eickhoff Bernhard (CC-AD/ESW1) <bernhard.eickhoff@de.bosch.com>
@bishibashiB bishibashiB force-pushed the feature/iox-#221_apply_cxx_list branch from d7c5b59 to ff08d01 Compare November 24, 2020 08:17
Copy link
Member

@elBoberido elBoberido left a comment

Choose a reason for hiding this comment

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

I just wanted to propose to split this up into multiple PR since I feared you would beat me for the longest open PR

@elfenpiff elfenpiff merged commit 65445be into eclipse-iceoryx:master Nov 25, 2020
@bishibashiB bishibashiB deleted the feature/iox-#221_apply_cxx_list branch November 25, 2020 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Replace occurence of std::list by cxx::list
5 participants