updated API + updated documentation
This commit is contained in:
parent
80fabe2397
commit
d2a52b1693
22
README.md
22
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 <memory>
|
||||
|
||||
void listen(uvw::Loop &loop) {
|
||||
std::shared_ptr<uvw::Tcp> tcp = loop.handle<uvw::Tcp>();
|
||||
std::shared_ptr<uvw::Tcp> tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable {
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().handle<uvw::Tcp>();
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().resource<uvw::Tcp>();
|
||||
|
||||
client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::Tcp &) mutable { ptr->close(); });
|
||||
client->on<uvw::EndEvent>([](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<uvw::Tcp>();
|
||||
auto tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
tcp->on<uvw::ErrorEvent>([](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<uvw::Tcp>();
|
||||
auto tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
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<uvw::Tcp>();
|
||||
auto tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::Tcp &srv) { /* something went wrong */ });
|
||||
|
||||
tcp->on<uvw::ListenEvent>([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable {
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().handle<uvw::Tcp>();
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().resource<uvw::Tcp>();
|
||||
client->once<uvw::EndEvent>([](const uvw::EndEvent &, uvw::Tcp &client) { client.close(); });
|
||||
client->on<uvw::DataEvent>([](const uvw::DataEvent &, uvw::Tcp &) { /* data received */ });
|
||||
srv.accept(*client);
|
||||
|
||||
@ -21,11 +21,7 @@ class Handle: public BaseHandle, public Resource<T> {
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
explicit Handle(ResourceType<U> rt, std::shared_ptr<Loop> ref)
|
||||
: BaseHandle{},
|
||||
Resource<T>{std::move(rt), std::move(ref)}
|
||||
{ }
|
||||
using Resource<T>::Resource;
|
||||
|
||||
template<typename U, typename F, typename... Args>
|
||||
bool initialize(F &&f, Args&&... args) {
|
||||
|
||||
@ -76,12 +76,19 @@ public:
|
||||
}
|
||||
|
||||
template<typename R, typename... Args>
|
||||
std::shared_ptr<R> handle(Args&&... args) {
|
||||
std::enable_if_t<std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
|
||||
resource(Args&&... args) {
|
||||
auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||
ptr = ptr->init() ? ptr : nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename R, typename... Args>
|
||||
std::enable_if_t<not std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
|
||||
resource(Args&&... args) {
|
||||
return R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void close() noexcept {
|
||||
auto err = uv_loop_close(loop.get());
|
||||
if(err) { publish(ErrorEvent{err}); }
|
||||
|
||||
@ -13,10 +13,7 @@ namespace uvw {
|
||||
template<typename T>
|
||||
class Request: public Resource<T> {
|
||||
protected:
|
||||
template<typename U>
|
||||
explicit Request(ResourceType<U> rt, std::shared_ptr<Loop> ref)
|
||||
: Resource<T>{std::move(rt), std::move(ref)}
|
||||
{ }
|
||||
using Resource<T>::Resource;
|
||||
|
||||
public:
|
||||
void cancel() noexcept {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
void listen(uvw::Loop &loop) {
|
||||
std::shared_ptr<uvw::Tcp> tcp = loop.handle<uvw::Tcp>();
|
||||
std::shared_ptr<uvw::Tcp> tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::Tcp &) {
|
||||
std::cout << "error " << std::endl;
|
||||
@ -15,7 +15,7 @@ void listen(uvw::Loop &loop) {
|
||||
tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &event, uvw::Tcp &srv) mutable {
|
||||
std::cout << "listen" << std::endl;
|
||||
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().handle<uvw::Tcp>();
|
||||
std::shared_ptr<uvw::Tcp> client = srv.loop().resource<uvw::Tcp>();
|
||||
|
||||
client->on<uvw::ErrorEvent>([](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<uvw::Tcp>();
|
||||
auto tcp = loop.resource<uvw::Tcp>();
|
||||
|
||||
tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::Tcp &) {
|
||||
std::cout << "error " << std::endl;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user