-
Notifications
You must be signed in to change notification settings - Fork 274
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
Refactor Selectables. Add support for selectable priorities #192
Conversation
common/ipaddress.h
Outdated
@@ -20,7 +20,7 @@ class IpAddress | |||
{ | |||
public: | |||
IpAddress() {} | |||
IpAddress(const ip_addr_t &ip) { m_ip = ip; } | |||
IpAddress(const ip_addr_t &ip) : m_ip(ip) {} |
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.
m_ip [](start = 37, length = 4)
Could you separate simple refactoring code like this into a smaller PR? so we could focus on more difficult one. #Closed
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 can, but it will take more time to extract all the changes and revert them back. Can you please consider to check them? They're tiny and follows just a few easy patterns:
func(object obj) -> func(const object& obj)
,
for(auto obj: object) -> for (const auto& obj: object)
'''
Class1::Class1(int var1)
{
m_var_1 = var1;
}
to
Class1::Class1(int var1) : m_var_1(var1) {}
#Closed
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 am thinking 'selectable improvement' as an experiment feature (not mature now). And other simple one are definitely good contribution to existing codebase. Considering the possibility of future reverting and/or conflicting, it's good to separate. Large amount of files in a PR always harm.
In reply to: 178991122 [](ancestors = 178991122)
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've removed the other changes. I kept only one bug with the missed va_end()
@@ -12,29 +15,32 @@ namespace swss { | |||
class Select | |||
{ | |||
public: | |||
Select(); | |||
~Select(); | |||
|
|||
/* Add object for select */ | |||
void addSelectable(Selectable *selectable); |
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.
addSelectable [](start = 9, length = 13)
suggest move all priority setting as addSelectable parameter, so no need to modify all the related classes. #Closed
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.
The classes are already changed. These changes won't affect any client code.
Also, I don't like to add information about priority into Select class.
Following the principle of Single Responsibility I want Select class only work for polling, not for something else.
Also, it's not easy to change Select::addSelectables() method which expects vector of Selectables.
Also, is makes Select class more complicated, we need to store and operate on the priority, which is Selectable attribute. #Pending
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.
Got your idea. Let me correct my comment. I suggest move all priority setting as function call to Selectable (not Select), keep original constructor signature, so no need to modify all the related sub classes. Another benefit is that all previous code with default priority will keep previous behavior. If any future user would like to apply different priority assignment, he just is able to do so explicitly.
Since all the sub classes has not used pri at all, keep all the modification in base class.
In reply to: 178991671 [](ancestors = 178991671)
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 don't agree with you. As soon as we create separate method to change priority it will not work as expected. For example, You create a Selectable, then add it into Select object and then change its priority. It will broke Select object, because it didn't expect anyone changes Selectable objects in the queue.
Also it's bad from design viewpoint. The priority property is 'CREATE_AND_SET' property in SAI terms. We don't want to change it as it created.
You mentioned "To support this feature Selectable interface was changed significantly." |
I must change Selectable interface because:
In this interface: readMe() allowed us to read information from Selectable which file descriptor signaled. Also I changed the previous Selectable interface because it leaked Select class methods into Selectables. |
common/select.h
Outdated
|
||
/* Add file-descriptor for select */ | ||
void addFd(int fd); | ||
/* Add multiple messages for select */ |
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.
messages [](start = 20, length = 8)
objects #Closed
common/selectable.h
Outdated
/* Read a message from the socket */ | ||
virtual void readMe() = 0; | ||
private: | ||
int m_priority; |
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.
m_priority [](start = 8, length = 10)
Add some comment about the definition. The larger, the higher priority? #Closed
common/selectable.h
Outdated
bool operator()(const Selectable* a, const Selectable* b) const | ||
{ | ||
if (a->getPri() == b->getPri()) | ||
return a > b; |
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 > b [](start = 23, length = 5)
Why define the order this way? The intuitive understanding is they are equal. #Closed
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.
Because std::set requires a functional object which defines order. By default it's std::less.
But I've defined my own order
http://en.cppreference.com/w/cpp/container/set
int res = ::epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, fd, NULL); | ||
if (res == -1) | ||
{ | ||
std::string error = std::string("Select::del_fd:epoll_ctl: error=(" |
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.
std:: [](start = 8, length = 5)
No need to add namespace #Pending
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 used to use prefixes to avoid ambiguity when reading.
string is so common name, so std::string looks much better.
Anyway we have ~800 usage of std in swss-common
$ grep 'std::' * | wc -l
804
common/select.cpp
Outdated
|
||
/* Checking caching from reader */ | ||
for (Selectable *i : m_objects) | ||
while (!m_ready.empty()) |
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.
while [](start = 4, length = 5)
Since you return in the block, why not use 'if'? #Closed
common/select.cpp
Outdated
timeout = -1; | ||
|
||
/* check if we have some data */ | ||
ret = select1(c, 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.
select1 [](start = 10, length = 7)
select1 is a weird name. #Closed
If we have selectables with equal priority, select will choose a selectable which was chosen before all others. So one selectable can't block others This commit also contains typo fix
This reverts commit bac891b.
Current master has broken unit tests. As soon as they are fixed, I'll resolve conflicts and make some requested changes. |
resolve conflict first? |
I've resolved the conflicts, but I have to check everything, until I'm sure everything is alright. |
retest this please |
All tests are done. The PR is ready for the final review |
common/selectable.h
Outdated
|
||
/* if the priorities are equal */ | ||
/* use Selectable which was selected later */ | ||
if (a->getLastTimeUsed() < b->getLastTimeUsed()) |
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.
getLastTimeUsed [](start = 19, length = 15)
The order is dynamic, I am afraid it will break the assumption of std::set
…l object, to avoid it using by others
Qi, I share your concern about the Comparator using the mutable state. But in this case I don't have any other simple solution. So what I did:
Also I have a comment about danger of using Selectalbe->updateLastUsedTime() on the Selectable which is inside of the set. |
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 have no more comments. Please check with other reviewers.
PLEASE DON'T PUSH THIS CHANGE. IT'LL BREAK BOTH SWSS AND SAIREDIS.
This refactoring introduce support of priorities for Selectables. Selectables with highest priorities will be selected first. If we have two selectables with the same priorities, the selectable which was accessed earliest will be chosen.
The priorities are defined as last argument of type int for following classes:
To support this feature Selectable interface was changed significantly.
Now Selectable has to provide following methods:
The method Select::select() was changed. int fd parameter was remove as not used anywhere*
I switched from Unix select() to Linux epoll which is more effective and easy to use.
Also I found that SelectableTimer could lose it's events, if reading rate is greater then timer interval. Probably it's a bug.
Also I made some other small changes and tweaks to improve performance of the swss-common. I'm going to create a separate PR with more performance changes for swss-common.