diff --git a/README.md b/README.md index 018cd530..0a03cb43 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ **Please, note that `uvw` is still a work in progress**. `uvw` is a header-only, event based, tiny and easy to use C++ wrapper for *libuv*. -The basic idea is to hide completely the *C-ish* interace of *libuv* behind a graceful C++ API. Currently, no `uv_*_t` data structure is actually exposed by the library. -Note that `uvw` stays true to the API of *libuv* and it doesn't add anything to its interface. For the same reason, users of the library must follow the same rules who are used to follow with *libuv*. +The basic idea is to hide completely the *C-ish* interface of *libuv* behind a graceful C++ API. Currently, no `uv_*_t` data structure is actually exposed by the library. +Note that `uvw` stays true to the API of *libuv* and it doesn't add anything to its interface. For the same reasons, users of the library must follow the same rules who are used to follow with *libuv*. As an example, a *handle* should be initialized before any other operation and closed once it is no longer in use. ## Code Example @@ -14,10 +14,10 @@ As an example, a *handle* should be initialized before any other operation and c #include void listen(uvw::Loop &loop) { - std::shared_ptr tcp = loop.handle(); + std::shared_ptr tcp = loop.resource(); tcp->once([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable { - std::shared_ptr client = srv.loop().handle(); + std::shared_ptr client = srv.loop().resource(); client->on([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::Tcp &) mutable { ptr->close(); }); client->on([](const uvw::EndEvent &, uvw::Tcp &client) { client.close(); }); @@ -31,7 +31,7 @@ void listen(uvw::Loop &loop) { } void conn(uvw::Loop &loop) { - auto tcp = loop.handle(); + auto tcp = loop.resource(); tcp->on([](const uvw::ErrorEvent &, uvw::Tcp &) { /* handle errors */ }); @@ -90,7 +90,7 @@ To navigate it with your favorite browser: There is only one rule when using `uvw`: always initialize the handles and close them. Handles keep themselves alive until one closes them. Because of that, leaks are possible if users simply forget about a handle. -To be honest, initialization is performed under the hood and can be even passed over, as far as resources are created using the `Loop::handle` member method. +To be honest, initialization is performed under the hood and can be even passed over, as far as resources are created using the `Loop::resource` member method. Thus the rule quickly becomes *always close your handles*. It's simple as calling the `close` member method on them. The first thing to do to use `uvw` is to create a loop. In case the default one is enough, it's easy as doing this: @@ -102,9 +102,9 @@ Loops can be run using the `run`, `runOnce` and `runWait` member methods. Please In order to create a handle and to bind it to the given loop, just do the following: - auto tcp = loop.handle(); + auto tcp = loop.resource(); -A tcp handle will be created and initialized, thus a shared pointer to that handle will be returned. +A tcp handle will be created and initialized, thus a shared pointer to the handle will be returned. Users should check if pointers have been correctly initialized: in case of errors, they won't be. Another way to create a handle is: @@ -113,7 +113,7 @@ Another way to create a handle is: Pretty annoying indeed. Using a loop is the recommended approach. -Once a handle has been created, it will keep itself alive until one invoke the `close` member method on it. +Once a handle has been created, it will keep itself alive until one invokes the `close` member method on it. To know what are the handles that are still alive and bound to a given loop, just do the following: loop.walk([](uvw::BaseHandle &){ /* application code here */ }); @@ -151,12 +151,12 @@ The code below shows how to create a simple tcp server using `uvw`: ``` auto loop = uvw::Loop::getDefault(); -auto tcp = loop.handle(); +auto tcp = loop.resource(); tcp->on([](const uvw::ErrorEvent &, uvw::Tcp &srv) { /* something went wrong */ }); tcp->on([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable { - std::shared_ptr client = srv.loop().handle(); + std::shared_ptr client = srv.loop().resource(); client->once([](const uvw::EndEvent &, uvw::Tcp &client) { client.close(); }); client->on([](const uvw::DataEvent &, uvw::Tcp &) { /* data received */ }); srv.accept(*client); diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp index 6e87ac6c..f20cc338 100644 --- a/src/uvw/handle.hpp +++ b/src/uvw/handle.hpp @@ -21,11 +21,7 @@ class Handle: public BaseHandle, public Resource { } protected: - template - explicit Handle(ResourceType rt, std::shared_ptr ref) - : BaseHandle{}, - Resource{std::move(rt), std::move(ref)} - { } + using Resource::Resource; template bool initialize(F &&f, Args&&... args) { diff --git a/src/uvw/loop.hpp b/src/uvw/loop.hpp index 95f4b08f..27daa66e 100644 --- a/src/uvw/loop.hpp +++ b/src/uvw/loop.hpp @@ -76,12 +76,19 @@ public: } template - std::shared_ptr handle(Args&&... args) { + std::enable_if_t::value, std::shared_ptr> + resource(Args&&... args) { auto ptr = R::create(shared_from_this(), std::forward(args)...); ptr = ptr->init() ? ptr : nullptr; return ptr; } + template + std::enable_if_t::value, std::shared_ptr> + resource(Args&&... args) { + return R::create(shared_from_this(), std::forward(args)...); + } + void close() noexcept { auto err = uv_loop_close(loop.get()); if(err) { publish(ErrorEvent{err}); } diff --git a/src/uvw/request.hpp b/src/uvw/request.hpp index 25f8a306..ec3603f3 100644 --- a/src/uvw/request.hpp +++ b/src/uvw/request.hpp @@ -13,10 +13,7 @@ namespace uvw { template class Request: public Resource { protected: - template - explicit Request(ResourceType rt, std::shared_ptr ref) - : Resource{std::move(rt), std::move(ref)} - { } + using Resource::Resource; public: void cancel() noexcept { diff --git a/test/main.cpp b/test/main.cpp index b085f446..1f87e951 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -6,7 +6,7 @@ void listen(uvw::Loop &loop) { - std::shared_ptr tcp = loop.handle(); + std::shared_ptr tcp = loop.resource(); tcp->on([](const uvw::ErrorEvent &, uvw::Tcp &) { std::cout << "error " << std::endl; @@ -15,7 +15,7 @@ void listen(uvw::Loop &loop) { tcp->once([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable { std::cout << "listen" << std::endl; - std::shared_ptr client = srv.loop().handle(); + std::shared_ptr client = srv.loop().resource(); client->on([](const uvw::ErrorEvent &, uvw::Tcp &) { std::cout << "error " << std::endl; @@ -62,7 +62,7 @@ void listen(uvw::Loop &loop) { void conn(uvw::Loop &loop) { - auto tcp = loop.handle(); + auto tcp = loop.resource(); tcp->on([](const uvw::ErrorEvent &, uvw::Tcp &) { std::cout << "error " << std::endl;