-
Notifications
You must be signed in to change notification settings - Fork 5.5k
header_map: copy constructor for HeaderMapImpl. #4129
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
Changes from 6 commits
01f7423
fffdbbc
b0aa98a
e5ce010
76dfa6c
080a830
f88da73
86cc2fa
d7d65ad
3c525eb
aa008ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -276,21 +276,10 @@ void HeaderMapImpl::appendToHeader(HeaderString& header, absl::string_view data) | |
|
|
||
| HeaderMapImpl::HeaderMapImpl() { memset(&inline_headers_, 0, sizeof(inline_headers_)); } | ||
|
|
||
| HeaderMapImpl::HeaderMapImpl(const HeaderMap& rhs) : HeaderMapImpl() { | ||
| rhs.iterate( | ||
| [](const HeaderEntry& header, void* context) -> HeaderMap::Iterate { | ||
| // TODO(mattklein123) PERF: Avoid copying here is not necessary. | ||
| HeaderString key_string; | ||
| key_string.setCopy(header.key().c_str(), header.key().size()); | ||
| HeaderString value_string; | ||
| value_string.setCopy(header.value().c_str(), header.value().size()); | ||
| HeaderMapImpl::HeaderMapImpl(const HeaderMap& rhs) : HeaderMapImpl() { copyFrom(rhs); } | ||
|
|
||
| static_cast<HeaderMapImpl*>(context)->addViaMove(std::move(key_string), | ||
| std::move(value_string)); | ||
| return HeaderMap::Iterate::Continue; | ||
| }, | ||
| this); | ||
| } | ||
| HeaderMapImpl::HeaderMapImpl(const HeaderMapImpl& rhs) | ||
| : HeaderMapImpl(static_cast<const HeaderMap&>(rhs)) {} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I'm confused. How is this different from what the compiler did before?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was synthesizing the default copy constructor, since we only supplied a constructor for the class we were deriving from AFAICT.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's something more going on here though, witness the build failures. Looking into this now. |
||
|
|
||
| HeaderMapImpl::HeaderMapImpl( | ||
| const std::initializer_list<std::pair<LowerCaseString, std::string>>& values) | ||
|
|
@@ -304,6 +293,22 @@ HeaderMapImpl::HeaderMapImpl( | |
| } | ||
| } | ||
|
|
||
| void HeaderMapImpl::copyFrom(const HeaderMap& header_map) { | ||
| header_map.iterate( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are defining a copy-ctor I think you should also define an assignment operator (and test it). https://en.cppreference.com/w/cpp/language/rule_of_three I see you are defining one in a test subclass, but it doesn't look like you've got one in HeaderMapImpl.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's fair. I will mvoe copy assignment to |
||
| [](const HeaderEntry& header, void* context) -> HeaderMap::Iterate { | ||
| // TODO(mattklein123) PERF: Avoid copying here is not necessary. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/is/if/ ? Do we keep a bit indicating whether a header-map contains owned strings or refs?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will fix typo, performance optimization is orthogonal. |
||
| HeaderString key_string; | ||
| key_string.setCopy(header.key().c_str(), header.key().size()); | ||
| HeaderString value_string; | ||
| value_string.setCopy(header.value().c_str(), header.value().size()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best practice is to use .data() rather than .c_str() here (x2), although I admit in practice I don't see how they can differ :)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no |
||
|
|
||
| static_cast<HeaderMapImpl*>(context)->addViaMove(std::move(key_string), | ||
| std::move(value_string)); | ||
| return HeaderMap::Iterate::Continue; | ||
| }, | ||
| this); | ||
| } | ||
|
|
||
| bool HeaderMapImpl::operator==(const HeaderMapImpl& rhs) const { | ||
| if (size() != rhs.size()) { | ||
| return false; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,8 +46,10 @@ class HeaderMapImpl : public HeaderMap { | |
| static void appendToHeader(HeaderString& header, absl::string_view data); | ||
|
|
||
| HeaderMapImpl(); | ||
| HeaderMapImpl(const std::initializer_list<std::pair<LowerCaseString, std::string>>& values); | ||
| HeaderMapImpl(const HeaderMap& rhs); | ||
| explicit HeaderMapImpl( | ||
| const std::initializer_list<std::pair<LowerCaseString, std::string>>& values); | ||
| explicit HeaderMapImpl(const HeaderMap& rhs); | ||
| HeaderMapImpl(const HeaderMapImpl& rhs); | ||
|
|
||
| /** | ||
| * Add a header via full move. This is the expected high performance paths for codecs populating | ||
|
|
@@ -80,6 +82,8 @@ class HeaderMapImpl : public HeaderMap { | |
| size_t size() const override { return headers_.size(); } | ||
|
|
||
| protected: | ||
| void copyFrom(const HeaderMap& rhs); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment that these are protected because they are suspected to be slow, and should only be used in tests? |
||
|
|
||
| struct HeaderEntryImpl : public HeaderEntry, NonCopyable { | ||
| HeaderEntryImpl(const LowerCaseString& key); | ||
| HeaderEntryImpl(const LowerCaseString& key, HeaderString&& value); | ||
|
|
@@ -131,7 +135,7 @@ class HeaderMapImpl : public HeaderMap { | |
| * List of HeaderEntryImpl that keeps the pseudo headers (key starting with ':') in the front | ||
| * of the list (as required by nghttp2) and otherwise maintains insertion order. | ||
| */ | ||
| class HeaderList { | ||
| class HeaderList : NonCopyable { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine to block move, but why not just block the implicit move constructor inside
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this change is needed anymore, but fine to keep. |
||
| public: | ||
| HeaderList() : pseudo_headers_end_(headers_.end()) {} | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -207,6 +207,17 @@ TestHeaderMapImpl::TestHeaderMapImpl( | |
|
|
||
| TestHeaderMapImpl::TestHeaderMapImpl(const HeaderMap& rhs) : HeaderMapImpl(rhs) {} | ||
|
|
||
| TestHeaderMapImpl& TestHeaderMapImpl::operator=(const TestHeaderMapImpl& other) { | ||
| if (&other == this) { | ||
| return *this; | ||
| } | ||
|
|
||
| removePrefix(LowerCaseString("")); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WDYT of factoring out a separate clear() method in the public API while you are in here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather not make any API public on
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If someone does need to clear(), I think it'd be better for it to be abstracted at the class interface. But a compromise might be to define clear() but make it private or protected, with a note about exposing it in the future if there's a real need.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Arguably, nobody should be doing this, |
||
| copyFrom(other); | ||
|
|
||
| return *this; | ||
| } | ||
|
|
||
| void TestHeaderMapImpl::addCopy(const std::string& key, const std::string& value) { | ||
| addCopy(LowerCaseString(key), value); | ||
| } | ||
|
|
||
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.
Is this change still needed? It's unclear to me why the compiler won't just pick the other one.
Uh oh!
There was an error while loading. Please reload this page.
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 think so; the implicit copy constructor is deleted, the above constructor for
HeaderMapisn't actually a copy constructor.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 see. OK.