-
Notifications
You must be signed in to change notification settings - Fork 373
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
Iox #221 apply cxx list #224
Conversation
2273d40
to
b7f9475
Compare
@@ -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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
{ | ||
auto interfacePortData = m_portPoolDataBase->m_interfacePortMembers.insert( | ||
auto interfacePortData = &m_portPoolDataBase->m_interfacePortMembers.emplace_front( | ||
iox::cxx::string<100>(iox::cxx::TruncateToCapacity, applicationName), interface); |
There was a problem hiding this comment.
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. 🦘
There was a problem hiding this comment.
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.
There was a problem hiding this 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 |
There was a problem hiding this comment.
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.
{ | ||
iox::popo::ApplicationPort applicationPort(applicationPortData); | ||
auto checkIter = iter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above...
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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
2161556
to
bf03943
Compare
iceoryx_posh/include/iceoryx_posh/internal/popo/receiver_handler.inl
Outdated
Show resolved
Hide resolved
@@ -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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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... ?
@@ -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>; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
Signed-off-by: Eickhoff Bernhard (CC-AD/ESW1) <bernhard.eickhoff@de.bosch.com>
d7c5b59
to
ff08d01
Compare
There was a problem hiding this 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
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.