diff --git a/src/uvw/event.hpp b/src/uvw/event.hpp index e642dc2b..36a70112 100644 --- a/src/uvw/event.hpp +++ b/src/uvw/event.hpp @@ -2,6 +2,7 @@ #include +#include #include #include "util.hpp" @@ -10,7 +11,16 @@ namespace uvw { struct BaseEvent { + BaseEvent() = default; + + BaseEvent(const BaseEvent &) = delete; + BaseEvent(BaseEvent &&) = delete; + + void operator=(const BaseEvent &) = delete; + void operator=(BaseEvent &&) = delete; + virtual ~BaseEvent() = 0; + static std::size_t next() noexcept { static std::size_t cnt = 0; return cnt++; @@ -33,7 +43,16 @@ struct CloseEvent: Event { }; struct ConnectEvent: Event { }; struct DataEvent: Event { - Buffer buffer{}; + explicit DataEvent(std::unique_ptr ptr, ssize_t l) + : dt{std::move(ptr)}, len{l} + { } + + const char * data() const noexcept { return dt.get(); } + ssize_t length() const noexcept { return len; } + +private: + std::unique_ptr dt; + ssize_t len; }; struct EndEvent: Event { }; diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp index bc2d04f8..74e2c85b 100644 --- a/src/uvw/handle.hpp +++ b/src/uvw/handle.hpp @@ -38,7 +38,8 @@ class Handle: public Emitter, public Self { }; static void closeCallback(uv_handle_t *handle) { - T &ref = *(static_cast(handle->data)); + Handle &ref = *(static_cast(handle->data)); + ref.initialized = false; ref.publish(CloseEvent{}); ref.reset(); } @@ -48,7 +49,8 @@ protected: explicit Handle(HandleType, std::shared_ptr ref) : Emitter{}, Self{}, wrapper{std::make_unique>()}, - pLoop{std::move(ref)} + pLoop{std::move(ref)}, + initialized{false} { this->template get()->data = static_cast(this); } @@ -62,13 +64,14 @@ protected: bool initialize(F &&f) { bool ret = true; - if(!active()) { + if(!initialized) { auto err = std::forward(f)(parent(), get()); if(err) { this->publish(ErrorEvent{err}); ret = false; } else { + initialized = true; this->leak(); } } @@ -105,6 +108,7 @@ public: private: std::unique_ptr wrapper; std::shared_ptr pLoop; + bool initialized; }; diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index 2dd15f5e..1ed1717c 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -19,29 +19,21 @@ class Stream: public Handle { static constexpr unsigned int DEFAULT_BACKLOG = 128; static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) { - buf->base = new char[suggested]; - buf->len = suggested; + *buf = uv_buf_init(new char[suggested], suggested); } - static void readCallback(uv_stream_t *handle, ssize_t nread, const uv_buf_t *cbuf) { + static void readCallback(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) { T &ref = *(static_cast(handle->data)); - uv_buf_t *buf = const_cast(cbuf); + // data will be destroyed no matter of what the value of nread is + std::unique_ptr data{buf->base}; if(nread == UV_EOF) { ref.publish(EndEvent{}); - delete[] buf->base; } else if(nread > 0) { - std::unique_ptr data{buf->base}; - DataEvent event; - event.buffer.reset(std::move(data), nread); - ref.publish(std::move(event)); + ref.publish(DataEvent{std::move(data), nread}); } else { ref.publish(ErrorEvent(nread)); - delete[] buf->base; } - - buf->base = nullptr; - buf->len = 0; } static void writeCallback(uv_write_t *req, int status) { @@ -90,19 +82,21 @@ public: this->invoke(&uv_read_stop, this->template get()); } - void write(Buffer buf) { - uv_buf_t data[] = { buf.uvBuf() }; + void write(std::unique_ptr data, ssize_t length) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), length) }; uv_write_t *req = new uv_write_t; - auto err = uv_write(req, this->template get(), data, 1, &Stream::writeCallback); + + auto err = uv_write(req, this->template get(), bufs, 1, &Stream::writeCallback); + if(err) { delete req; this->publish(ErrorEvent{err}); } } - int tryWrite(Buffer buf) noexcept { - uv_buf_t data[] = { buf.uvBuf() }; - auto bw = uv_try_write(this->template get(), data, 1); + int tryWrite(std::unique_ptr data, ssize_t length) noexcept { + uv_buf_t bufs[] = { uv_buf_init(data.get(), length) }; + auto bw = uv_try_write(this->template get(), bufs, 1); if(bw < 0) { this->publish(ErrorEvent{bw}); diff --git a/src/uvw/util.hpp b/src/uvw/util.hpp index 50afdef0..665fdec1 100644 --- a/src/uvw/util.hpp +++ b/src/uvw/util.hpp @@ -70,33 +70,4 @@ private: using Addr = std::pair; -class Buffer final { - template - friend class Stream; - - uv_buf_t uvBuf() const noexcept { - return uv_buf_init(data.get(), size); - } - -public: - Buffer(): data{}, size{} { } - - Buffer(std::unique_ptr dt, std::size_t s) - : data{std::move(dt)}, size{s} - { } - - Buffer(Buffer &&) = default; - Buffer& operator=(Buffer &&) = default; - - void reset(std::unique_ptr dt, std::size_t s) noexcept { - data.swap(dt); - size = s; - } - -private: - std::unique_ptr data; - std::size_t size; -}; - - } diff --git a/test/main.cpp b/test/main.cpp index 8a8b5a56..8dac39ab 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -21,7 +21,7 @@ void listen(uvw::Loop &loop) { std::cout << "error " << std::endl; }); - client->on([resource = srv.shared_from_this()](uvw::CloseEvent, uvw::Tcp &) mutable { + client->on([resource = srv.shared_from_this()](const uvw::CloseEvent &, uvw::Tcp &) mutable { std::cout << "close" << std::endl; uvw::Tcp &srv = *resource; @@ -37,7 +37,8 @@ void listen(uvw::Loop &loop) { std::cout << "remote: " << remote.first << " " << remote.second << std::endl; client->on([](const uvw::DataEvent &event, uvw::Tcp &) { - std::cout << "data" << std::endl; + std::cout.write(event.data(), event.length()) << std::endl; + std::cout << "data length: " << event.length() << std::endl; }); client->on([](const uvw::EndEvent &, uvw::Tcp &client) { @@ -64,15 +65,20 @@ void conn(uvw::Loop &loop) { std::cout << "error " << std::endl; }); + tcp->once([](const uvw::WriteEvent &, uvw::Tcp &tcp) mutable { + std::cout << "write" << std::endl; + tcp.close(); + }); + tcp->once([](const uvw::ConnectEvent &, uvw::Tcp &tcp) mutable { std::cout << "connect" << std::endl; - auto data = std::unique_ptr(new char[1]); - data[0] = 'a'; - uvw::Buffer buf{std::move(data), 1}; - int bw = tcp.tryWrite(std::move(buf)); + auto dataTryWrite = std::unique_ptr(new char[1]{ 'a' }); + int bw = tcp.tryWrite(std::move(dataTryWrite), 1); std::cout << "written: " << ((int)bw) << std::endl; - tcp.close(); + + auto dataWrite = std::unique_ptr(new char[2]{ 'b', 'c' }); + tcp.write(std::move(dataWrite), 2); }); tcp->once([](const uvw::CloseEvent &, uvw::Tcp &) mutable {