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

Implemented #320. #339

Merged
merged 10 commits into from
Aug 22, 2019
Merged

Implemented #320. #339

merged 10 commits into from
Aug 22, 2019

Conversation

redboltz
Copy link
Owner

Added buffer class that supports mqtt::string_view compatible
behavior and life keekping mechanism (optional).

Callback functions for users hold receive buffer directly via
buffer.

Removed *_ref properties. Ref or not ref is hidden by buffer.
Added ""_mb user defined literals for buffer.

Added boost type_erasure.
mqtt::socket is type erased socket. It covers tcp, tls, ws, and wss.
Compile times become faster.

Replaced static_cast with boost::numeric_cast if overflow could happen.
Removed redundant static_cast.

Implemented efficient shared_ptr_array allocation.

If use boost (default), then use boost::make_shared<char[]>(size).
If user defines MQTT_STD_SHARED_PTR_ARRAY,
if __cplusplus is greater than 201703L (means C++20 or later),
then std::make_shared<char[]>(size),
otherwise std::shared_ptr<char[]>(new size)
is called.

Added buffer class that supports `mqtt::string_view` compatible
behavior and life keekping mechanism (optional).

Callback functions for users hold receive buffer directly via
`buffer`.

Removed `*_ref` properties. Ref or not ref is hidden by `buffer`.
Added `""_mb` user defined literals for `buffer`.

Added boost type_erasure.
`mqtt::socket` is type erased socket. It covers tcp, tls, ws, and wss.
Compile times become faster.

Replaced static_cast with boost::numeric_cast if overflow could happen.
Removed redundant static_cast.

Implemented efficient shared_ptr_array allocation.

If use boost (default), then use `boost::make_shared<char[]>(size)`.
If user defines MQTT_STD_SHARED_PTR_ARRAY,
    if __cplusplus is greater than 201703L (means C++20 or later),
        then `std::make_shared<char[]>(size)`,
        otherwise `std::shared_ptr<char[]>(new size)`
    is called.
@redboltz redboltz mentioned this pull request Aug 18, 2019
@codecov-io
Copy link

codecov-io commented Aug 18, 2019

Codecov Report

Merging #339 into master will increase coverage by 0.72%.
The diff coverage is 78.63%.

@@            Coverage Diff             @@
##           master     #339      +/-   ##
==========================================
+ Coverage   85.53%   86.25%   +0.72%     
==========================================
  Files          34       37       +3     
  Lines        4889     6215    +1326     
==========================================
+ Hits         4182     5361    +1179     
- Misses        707      854     +147

.travis.yml Outdated
@@ -1,6 +1,6 @@
sudo: false
language: cpp
dist: trusty
dist: bionic
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm still cautious about changes to the minimum compiler version.

Did this turn out to still be necessary?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Maybe I can move back to trusty. Would you want to do that?

Copy link
Contributor

@jonesmz jonesmz Aug 20, 2019

Choose a reason for hiding this comment

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

If it's practical.

If trusty is not "really" too old, and there's an "easy" solution to the compiler issues, then I would prefer to keep supporting trusty, but I'm not opposed to Bionic, as long as the compiler series is still the GCC 7.x.y release.

Like I said, I'm currently stuck on 7.3.0, which supports most of C++17, and it looks like Bionic has GCC 7.4.0, which is probably close enough.

But I'm saying that if there isn't otherwise a reason to switch to the newer version (because compiler errors, for example) then we shouldn't change the minimum version.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ok, I will downgrade to trusty.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I just confirmed the current version of impl_320_2 works fine with trusty. I will use trusty.

Copy link
Owner Author

Choose a reason for hiding this comment

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

done(just my memo, not pushed yet).

Copy link
Contributor

Choose a reason for hiding this comment

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

This change does not appear to have been reverted.

Did you revert it?

mqtt::v5::property::user_property("key2", "val2"),
mqtt::v5::property::authentication_method("test authentication method"),
mqtt::v5::property::authentication_data("test authentication data")
mqtt::v5::property::user_property("key1"_mb, "val1"_mb),
Copy link
Contributor

Choose a reason for hiding this comment

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

We could do a user defined literal for UserProperties as well, but it's not clear to me if that is better, or worse, than this approach. Perhaps something that we shouldn't provide at the library level. Or if we did, as a separate header file that people have to include themselves "for convenience".

inline mqtt::v5::property::user_property operator""_user_property(char const* str, std::size_t length) {
    // Search for separator character (Not sure what character to use. ';' could be one.
    // Not knowing the right separator character is the reason why i say we probably shouldn't provide this function.
    // return { mqtt::buffer(string_view of first part), mqtt::buffer(string_view of second part));
}

Copy link
Owner Author

Choose a reason for hiding this comment

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

This PR is already very big and contains many(?) breaking changes. I'd like to consider the issue after the PR merged. Could you create a new issue for that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can make an issue.

I'm not sure it's a good idea.

Do you think it's a good idea to offer user-defined literals for all of the property types?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that it is good idea for all single string-base properties such as Content Type, Response Topic.
It is not good for binary-base properties such as Correlation Data.

UserProperty is difficult. I think that user defined literals is not sutable for UserProperty. Because separator is required. I think that mqtt::v5::property::user_property("key1"_mb, "val1"_mb) is simple enough.

@@ -0,0 +1,67 @@
// Copyright Takatoshi Kondo 2019
Copy link
Contributor

Choose a reason for hiding this comment

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

For reference, here's the design for a "Shared String", that I use for my own code. (Note: Does not support custom allocators yet. Haven't had time)

Not saying your design is better or worse. Just showing you for sake of sharing design ideas.

I'd be happy to see some of my implementation ideas incorporated into mqtt_cpp, but it's certainly not necessary.

Having mqtt::buffer use a boost::shared_ptr under the hood means that I'm able to write a trivial conversion function from mqtt::buffer -> my "BasicSharedString" code.

https://pastebin.com/2xeqEniX

Copy link
Owner Author

Choose a reason for hiding this comment

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

Thank you for sharing. I will check it later.

Copy link
Contributor

Choose a reason for hiding this comment

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

Was the BasicSharedString implementation that I shared interesting to you?


inline namespace literals {

inline buffer operator""_mb(char const* str, std::size_t length) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably put a brief comment here explaining that strings where user defined literals are used have indefinite lifetime in the read-only data section of the binary, and therefore no reference counting is needed.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will add comments.

Copy link
Owner Author

Choose a reason for hiding this comment

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

done(just my memo, not pushed yet).

namespace boost {
namespace asio {

inline const_buffer buffer(mqtt::buffer const& data) {
Copy link
Contributor

Choose a reason for hiding this comment

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

A brief comment explaining that management of the mqtt::buffer.lifetime_ needs to happen outside the boost::asio::buffer, e.g. with the "life_keeper" parameters or similar.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will add the comment.

Copy link
Owner Author

Choose a reason for hiding this comment

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

done(just my memo, not pushed yet).

base::socket() = std::move(socket);
connect_impl(*base::socket(), it, end, std::move(props), std::move(func));
socket_ = std::move(socket);
base::socket_optional().emplace(socket_);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why make the socket optional for the base class? That seems weird, that an mqtt::endpoint could ever exist without a socket.

Can the socket be replaced during a session, for example?

Copy link
Owner Author

Choose a reason for hiding this comment

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

It is the most difficult and controversy point of the PR I think.
Let me explain.

  • The optional is only for lazy initialization. Once the socket is created then it would never be updated.
  • The design is the same as the current master.
    /**
    * @brief Get Socket shared_ptr reference.
    * @return refereence of Socket unique_ptr
    */
    std::shared_ptr<Socket>& socket() {
    return socket_;
    }

    void connect(std::vector<v5::property_variant> props, async_handler_t func = async_handler_t()) {
    as::ip::tcp::resolver r(ios_);
    #if BOOST_VERSION < 106600
    as::ip::tcp::resolver::query q(host_, port_);
    auto it = r.resolve(q);
    as::ip::tcp::resolver::iterator end;
    #else // BOOST_VERSION < 106600
    auto eps = r.resolve(host_, port_);
    auto it = eps.begin();
    auto end = eps.end();
    #endif // BOOST_VERSION < 106600
    setup_socket(base::socket());
    connect_impl(*base::socket(), it, end, std::move(props), std::move(func));
    }

    #if !defined(MQTT_NO_TLS)
    template <typename Strand>
    void setup_socket(std::shared_ptr<tcp_endpoint<as::ssl::stream<as::ip::tcp::socket>, Strand>>& socket) {
    socket.reset(new Socket(ios_, ctx_));
    }
    • On TLS connection, user needs to setup ssl::context before connect. The socket requires ssl::context as the constructor parameter. So the socket should be created in the connect(), not in the client constructor. However, endpoint has the member of shared_ptr<Scoket>, so it is initialized as nullptr at construction time. Then lazy initialized in connect(). This is the original (master) design.

    • In order to do the same things, I introduced optional in this PR. Because shared_any cannot be initialized by nullptr. Because it requires a reference of the pointee that is hold by the shared_ptr.

That is the reason I introduced optional.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for the explanation.

I'd rather this change be done separately from the mqtt::buffer changes

But I understand that that is a lot of work to separate the two changes.

Thoughts?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I'd rather this change be done separately from the mqtt::buffer changes
But I understand that that is a lot of work to separate the two changes.

Yes it is difficult. I can't separate them. Because type erasure is required for zero copy buffer without increasing compile times. So I'd like to go this way.

BTW, API socket_optional() is protected. So ordinary user doesn't care about optional.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can they be separated into two separate commits, on the same PR?

Copy link
Owner Author

Choose a reason for hiding this comment

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

If we keep successful compile result, we can't do that. Because zero copy and not slow compile times required both.

Once I commit slower compile times version, and then modify it, it could be possible but it is hard to me. It is unnecessary work and might take a long time.
So I'd like to commit them in the same commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alright.

I understand.

I'm still not sure what causes the increased compile times, which is why I wanted to see your code by itself, but I understand that it's extra work.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I pushed the slow compile times branch that is not type erased.

It is not continuous to the current impl_320_2 branch but it might help to analyze the reason of compile times increasing.

https://github.com/redboltz/mqtt_cpp/tree/impl_320_no_te_slow_compile


// process common

templat
Copy link
Contributor

@jonesmz jonesmz Aug 19, 2019

Choose a reason for hiding this comment

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

would

static constexpr char version_string = { 0x00, 0x04, 'M', 'Q', 'T', 'T' };
memcmp(buf, version_string, sizeof(version_string) != 0 

be easier for people to read and understand?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. Something is wrong.

I was talking about where you compare the protocol identifier string on the incoming message.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ok, I will fix it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

done(just my memo, not pushed yet).


// process common

templat
Copy link
Contributor

Choose a reason for hiding this comment

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

Not actually using anything captured by reference.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. This comment went to the wrong place somehow...

I was pointing out that there are some lambda functions in one of the process_*** functions that are

[&](){...}

But don't actually use any of the variables in the local context. So the & can be removed.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will fix it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I noticed that [&] is for this. version_ is referred int the lambda expression.
I know that it is better to write the capture list explicitly but in this case, the lambda expression is defined and called in the same time. Dangling reference can't happen. Only in this case, I think that [&] is acceptable. It is easy to maintain.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. Sounds good.


// process common

templat
Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?


// process common

templat
Copy link
Contributor

Choose a reason for hiding this comment

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

static constexpr

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?

Copy link
Contributor

Choose a reason for hiding this comment

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

There are several

std::size_t size = ...

statements that are inside the "process_***" functions.

Those size variables could be static constexpr

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will fix it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

done(just my memo, not pushed yet).


// process common

templat
Copy link
Contributor

Choose a reason for hiding this comment

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

How practical would it be to make all of these process_*** functions into free functions, that accessed the member variables of the endpoint object via the passed in std::shared_ptr<endpoint<>> parameter?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?

Copy link
Contributor

Choose a reason for hiding this comment

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

The code reference is wrong, but I was talking about process_connect, and process_pingresp and similar.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Some of proces_* functions access buf_ member variable to avoid allocation. It is a private member of endpoint.
For example https://github.com/redboltz/mqtt_cpp/blob/impl_320_2/include/mqtt/endpoint.hpp#L8487-L8505

I think that they should be member function and not practical to become free function. I think that frined function with endpoint parameter is worse than member function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. I understand.


// process common

templat
Copy link
Owner Author

Choose a reason for hiding this comment

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

I think that the code reference is something wrong. Could you update it?

@redboltz
Copy link
Owner Author

I believe that I replied all of your comments.

Before I update the code, could you check my comments?

@jonesmz
Copy link
Contributor

jonesmz commented Aug 20, 2019

I think there may have been several places where comments were hidden that you did not see.

I pointed out 2 of them, but there were multiple that I didn't see any response from you.

* Reverted travis-ci linux distro to trusty from bionic.
* Added documents for mqtt::buffer.
* Added documents for mqtt::shared_ptr_array.
* Added documents for mqtt::shared_any.
* Removed unused include.
* Added mqtt::buffer allocating function.
* Replaced `&buf[0]` with `buf.data()` and `&buf_[0]` with `buf_.data()`.
* Replaced `buf[0]` with `buf.front()` and `buf_[0]` with `buf_.front()` except continuous `buf[0]` amd `buf[1]` case.
* Improved lambda capture on `async_read()`.
* Replaced `static_cast` with `boost::numeric_cast` if error could happen.
* Added comments for rvalue reference parameters in the local lambda expressions.
* Added `calc_variable_length()` to avoid code repeatation.
* Replaced `type const val = ...` with `static constexpr type const val = ...`.
* Improved MQTT protocol name conparison.
* Replaced `mqtt::string_view` passed by const reference with passed by value.
* Replaced `buf = std::move(buf).substr(N)` with `buf.remove_prefix(N)`.
* Replaecd iterator with plus operator with `std::next()`.
* Fixed `topic_name_length_buf_` usage to easy to understand.
* Fixed `parse_one()` return value and parameter to passed by reference.
* Removed code repeatation from `shared_any`.
@redboltz
Copy link
Owner Author

I just pushed the commit that fixes all of codes that I commented "done(just my memo, not pushed yet).".

@jonesmz
Copy link
Contributor

jonesmz commented Aug 21, 2019

Ok.

Do you think it's ready to submit now?

Should I go through it one more time?

@redboltz
Copy link
Owner Author

I believe that it is ready to merge now.
But if you have time, could you check the PR once more?

@jonesmz
Copy link
Contributor

jonesmz commented Aug 21, 2019

I will check it once more right now.

It will take approximately 1 hr.

Can we merge in approximately 1hr, if I don't see any problems?

@redboltz
Copy link
Owner Author

Sounds good. Thank you very much!

/**
* @brief shared_ptr_array creating function.
* You can choose the target type.
* - If MQTT_STD_SHARED_PTR_ARRAY is defined,
Copy link
Contributor

@jonesmz jonesmz Aug 21, 2019

Choose a reason for hiding this comment

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

The CMakeLists.txt file does not offer an option to control this behavior, because this PR does not include changes to CMakeLists.txt

Was that something you planned to do?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I forgot adding MQTT_STD_SHARED_PTR_ARRAY to CMakeLists.txt. I will add the following code to CMakeLists.txt.

OPTION(MQTT_STD_SHARED_PTR_ARRAY "Use std::shared_ptr<char[]> from C++17 instead of boost::shared_ptr<char[]>" OFF)

...

IF (MQTT_STD_SHARED_PTR_ARRAY)
    SET(CMAKE_CXX_STANDARD 17)
    SET(CMAKE_CXX_STANDARD_REQUIRED ON)
    MESSAGE (STATUS "Using std::shared_ptr<char []> instead of boost::shared_ptr<char []>. Enables C++17!!!")
    SET (CMAKE_CXX_FLAGS "-DMQTT_STD_SHARED_PTR_ARRAY ${CMAKE_CXX_FLAGS}")
ELSE ()
    MESSAGE (STATUS "Using boost::shared_ptr<char []> instead of boost::shared_ptr<char []>")
ENDIF ()

topic_name_ = as::buffer(&*b, topic_name_length);
b += topic_name_length;
if (buf.size() < topic_name_length) throw remaining_length_error();
utf8string_check(static_cast<mqtt::string_view>(buf).substr(0, topic_name_length));
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment here explaining why you cast to mqtt::string_view would help future contributors.

In this case, the reason is to avoid increasing the reference count of buf when .substr() is called.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I agree. I will add a comment.

BOOST_TEST(v2.val() == v_ref2.val());

BOOST_AUTO_TEST_CASE( content_type ) {
mqtt::v5::property::content_type v1 { "abc"_mb };
BOOST_TEST(boost::lexical_cast<std::string>(v1) == "abc");
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand how boost::lexical_cast knows what to do with mqtt::v5::property::content_type ...?

Can you help me understand?

Copy link
Owner Author

Choose a reason for hiding this comment

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

This is a test for

std::ostream& operator<<(std::ostream&, mqtt::v4::property::content_type const&);

lexical_cast uses stream output operator. https://www.boost.org/doc/libs/1_71_0/doc/html/boost_lexical_cast/synopsis.html#boost_lexical_cast.synopsis.lexical_cast

It is easy to write test codes so I use lexical_cast.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I did not know that. Thank you for explaining.

@@ -915,123 +559,51 @@ class user_property_ref {
std::size_t num_of_const_buffer_sequence() const {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't this function be static constexpr?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yes, it should be. I will fix it. Including other three member functions.

@@ -869,31 +512,32 @@ class user_property_ref {
void add_const_buffer_sequence(std::vector<as::const_buffer>& v) const {
v.emplace_back(as::buffer(&id_, 1));
v.emplace_back(as::buffer(key_.len.data(), key_.len.size()));
v.emplace_back(key_.str);
v.emplace_back(as::buffer(key_.buf.data(), key_.buf.size()));
Copy link
Contributor

Choose a reason for hiding this comment

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

We now support

as::buffer(key_.buf)

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ah yes, I will replace it.

@jonesmz
Copy link
Contributor

jonesmz commented Aug 21, 2019

I have reviewed all files except endpoint.hpp.

I am reviewing endpoint.hpp now.

typename std::iterator_traits<Iterator>::iterator_category,
std::random_access_iterator_tag
>::value,
"Iterator doesn't support random access"
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe better wording:

Iterators provided to restore_serialized_message() must be random access iterators.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Thanks, I use your wording.

restore_serialized_message(basic_pubrel_message<PacketIdBytes>(b, e));
restore_serialized_message(
basic_pubrel_message<PacketIdBytes>(
buffer(string_view(&*b, static_cast<std::size_t>(std::distance(b, e))))
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment explaining why you construct the mqtt::buffer such that it does not own the data would be good to have.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will add the following comment:

// basic_pubrel_message have no member variable that type is mqtt::buffer.
// When creating basic_pubrel_message, the constructor just read mqtt::buffer
// and convert to some values.
// So the argument buffer(...) doesn't need to hold the lifetime.

async_handler_t func,
buffer buf,
std::size_t size,
std::function<void(buffer, buffer, async_handler_t, this_type_sp)> handler,
Copy link
Contributor

Choose a reason for hiding this comment

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

Would doing

using process_handler_t = std::function<void(buffer, buffer, async_handler_t, this_type_sp)>;

improve the code?

Copy link
Owner Author

Choose a reason for hiding this comment

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

There are some variations as follows:

        std::function<void(packet_id_t, buffer, async_handler_t, this_type_sp)> handler,
        std::function<void(buffer, buffer, async_handler_t, this_type_sp)> handler,

So if we introduce type aliases, naming is difficult. I think that current implementation is good enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok.

call_message_size_error_handlers(func);
return;
}
if (buf.front() & 0b10000000) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that 0b10000000 should be a named constant.

E.g.

static constexpr std::uint8_t variable_length_flag = 0b10000000

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ok I will introduce the constant.

if (!check_error_and_transferred_length(ec, func, bytes_transferred, 1)) return;
proc(
std::move(func),
buffer(string_view(buf_.data(), 1)),
Copy link
Contributor

Choose a reason for hiding this comment

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

Make a comment saying the lifetime of buf_ is handled by self

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will add comment.

if (property_length_rest < len) {
call_message_size_error_handlers(func);
return;

Copy link
Contributor

Choose a reason for hiding this comment

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

Typos.

paramter = parameter
controll = control

Copy link
Owner Author

Choose a reason for hiding this comment

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

I will fix them.

@jonesmz
Copy link
Contributor

jonesmz commented Aug 21, 2019

I've reviewed about 2/3 of endpoint.hpp, and haven't seen any major problems.

I think i'm going to stop now, I ran out of time.

I think this pull request can be merged when you've reviewed my comments from the last hour.

@jonesmz
Copy link
Contributor

jonesmz commented Aug 21, 2019

Also, did you notice that the PR does not think that changes to .travis.yaml were reverted?

@redboltz
Copy link
Owner Author

redboltz commented Aug 21, 2019

Also, did you notice that the PR does not think that changes to .travis.yaml were reverted?

It should be reverted to trusty. I made a mistake to remove that commit. I will fix it.
In addition, add -DMQTT_STD_SHARED_PTR_ARRAY=ON build.

Removed magic number and add constant.
Added comments for developer.
Updated `num_of_const_buffer_sequence()` from member function to
static constexpr function.
I don't know way but codecov upload failed on `pr`.
@jonesmz
Copy link
Contributor

jonesmz commented Aug 22, 2019

Looking good!

@redboltz redboltz merged commit f5cb4c5 into master Aug 22, 2019
@redboltz redboltz deleted the impl_320_2 branch August 22, 2019 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants