1  **Sponsored and contributed by [Cynny SpA](https://www.cynny.com/).**
3 # uvw - libuv wrapper in modern C++
5 [](https://travis-ci.org/skypjack/uvw)
6 [](https://ci.appveyor.com/project/skypjack/uvw)
7 [](https://coveralls.io/github/skypjack/uvw?branch=master)
8 [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=W2HF9FESD5LJY&lc=IT&item_name=Michele%20Caini¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)
12 `uvw` is a header-only, event based, tiny and easy to use *libuv* wrapper in modern C++.<br/>
13 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.<br/>
14 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*.<br/>
15 As an example, a *handle* should be initialized before any other operation and closed once it is no longer in use.
23 void listen(uvw::Loop &loop) {
24 std::shared_ptr<uvw::TcpHandle> tcp = loop.resource<uvw::TcpHandle>();
26 tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TcpHandle &srv) {
27 std::shared_ptr<uvw::TcpHandle> client = srv.loop().resource<uvw::TcpHandle>();
29 client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::TcpHandle &) { ptr->close(); });
30 client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TcpHandle &client) { client.close(); });
36 tcp->bind("127.0.0.1", 4242);
40 void conn(uvw::Loop &loop) {
41 auto tcp = loop.resource<uvw::TcpHandle>();
43 tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* handle errors */ });
45 tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::TcpHandle &tcp) {
46 auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
47 tcp.write(std::move(dataWrite), 2);
51 tcp->connect(std::string{"127.0.0.1"}, 4242);
55 auto loop = uvw::Loop::getDefault();
64 The main reason for which `uvw` has been written is the fact that it does not exist a valid *libuv* wrapper in C++. That's all.
70 To be able to use `uvw`, users must provide the following system-wide tools:
72 * A full-featured compiler that supports at least C++14.
73 * `libuv` (which version depends on the tag of `uvw` in use).
75 The requirements below are mandatory to compile the tests and to extract the documentation:
77 * CMake version 3.2 or later.
78 * Doxygen version 1.8 or later.
80 Note that `libuv` is part of the dependencies of the project and it will be cloned by `cmake` (see below for further details).<br/>
81 Because of that, users have not to install it to compile and execute the tests.
85 `uvw` is a header-only library.<br/>
86 This means that including the `uvw.hpp` header or one of the other `uvw/*.hpp` headers is enough to use it.<br/>
87 It's a matter of adding the following line at the top of a file:
93 Then pass the proper `-I` argument to the compiler to add the `src` directory to the include paths.<br/>
94 Note that users are demanded to correctly setup include directories and libraries search paths for *libuv*.
98 Starting with tag _v1.12.0_ of `libuv`, `uvw` follows the [semantic versioning](http://semver.org/) scheme.<br/>
99 The problem is that any version of `uvw` also requires to track explicitly the version of `libuv` to which it is bound.<br/>
100 Because of that, the latter wil be appended to the version of `uvw`. As an example:
104 In particular, the following applies:
106 * _U.V.W_ are major, minor and patch versions of `uvw`.
107 * _X.Y_ is the version of `libuv` to which to refer (where any patch version is valid).
109 In other terms, tags will look like this from now on:
113 Branch `master` of `uvw` will be a work in progress branch that follows branch _v1.x_ of `libuv` (at least as long as it remains their _master_ branch).<br/>
119 The documentation is based on [`doxygen`](http://www.stack.nl/~dimitri/doxygen/). To build it:
125 The API reference will be created in HTML format within the directory `build/docs/html`.<br/>
126 To navigate it with your favorite browser:
129 * `$ your_favorite_browser docs/html/index.html`
135 There is only one rule when using `uvw`: always initialize the resources and terminate them.
137 Resources belong mainly to two families: _handles_ and _requests_.<br/>
138 Handles represent long-lived objects capable of performing certain operations while active.<br/>
139 Requests represent (typically) short-lived operations performed either over a handle or standalone.
141 The following sections will explain in short what it means to initialize and terminate these kinds of resources.
145 Initialization is usually performed under the hood and can be even passed over, as far as handles are created using the `Loop::resource` member function.<br/>
146 On the other side, handles keep themselves alive until one explicitly closes them. Because of that, memory usage will grow up if users simply forget about a handle.<br/>
147 Therefore the rule quickly becomes *always close your handles*. It's as simple as calling the `close` member function on them.
151 Usually initializing a request object is not required. Anyway, the recommended way to create a request is still through the `Loop::resource` member function.<br/>
152 Requests will keep themselves alive as long as they are bound to unfinished underlying activities. This means that users have not to discard explicitly a request.<br/>
153 Therefore the rule quickly becomes *feel free to make a request and forget about it*. It's as simple as calling a member function on them.
155 #### The Loop and the Resource
157 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:
160 auto loop = uvw::Loop::getDefault();
163 Note that loop objects don't require to be closed explicitly, even if they offer the `close` member function in case an user wants to do that.<br/>
164 Loops can be started using the `run` member function. The two calls below are equivalent:
168 loop->run<uvw::Loop::Mode::DEFAULT>
171 Available modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the documentation of *libuv* for further details.
173 In order to create a resource and to bind it to the given loop, just do the following:
176 auto tcp = loop.resource<uvw::TcpHandle>();
179 The line above will create and initialize a tcp handle, then a shared pointer to that resource will be returned.<br/>
180 Users should check if pointers have been correctly initialized: in case of errors, they won't be.<br/>
181 Another way to create a resource is:
184 auto tcp = TcpHandle::create(loop);
188 Pretty annoying indeed. Using a loop is the recommended approach.
190 The resources also accept arbitrary user-data that won't be touched in any case.<br/>
191 Users can set and get them through the `data` member function as it follows:
194 resource->data(std::make_shared<int>(42));
195 std::shared_ptr<void> data = resource->data();
198 Resources expect a `std::shared_pointer<void>` and return it, therefore any kind of data is welcome.<br/>
199 Users can explicitly specify a type other than `void` when calling the `data` member function:
202 std::shared_ptr<int> data = resource->data<int>();
205 Remember from the previous section that a handle will keep itself alive until one invokes the `close` member function on it.<br/>
206 To know what are the handles that are still alive and bound to a given loop, just do the following:
209 loop.walk([](uvw::BaseHandle &){ /* application code here */ });
212 `BaseHandle` exposes a few methods and cannot be promoted to the original type of the handle (even though `type` and `category` member functions fill the gap somehow).<br/>
213 Anyway, it can be used to close the handle that originated from it. As an example, all the pending handles can be closed easily as it follows:
216 loop.walk([](uvw::BaseHandle &h){ h.close(); });
219 No need to keep track of them.
221 To know what are the available resources' types, please refer the API reference.
223 #### The event-based approach
225 For `uvw` offers an event-based approach, resources are small event emitters to which listeners can be attached.<br/>
226 Attaching a listener to a resource is the recommended way to be notified about changes.<br/>
227 Listeners must be callable objects of type `void(EventType &, ResourceType &)`, where:
229 * `EventType` is the type of the event for which they have been designed.
230 * `ResourceType` is the type of the resource that has originated the event.
232 It means that the following function types are all valid:
234 * `void(EventType &, ResourceType &)`
235 * `void(const EventType &, ResourceType &)`
236 * `void(EventType &, const ResourceType &)`
237 * `void(const EventType &, const ResourceType &)`
239 Once more, please note that there is no need to keep around references to the resources: they will pass themselves as an argument whenever an event is published.
241 There exist two methods to attach an event to a resource:
243 * `resource.once<EventType>(listener)`: the listener will be automatically removed after the first event of the given type.
244 * `resource.on<EventType>(listener)`: to be used for long-running listeners.
246 Both of them return an object of type `ResourceType::Connection` (as an example, `TcpHandle::Connection`).<br/>
247 A connection object can be used later as an argument to the `erase` member function of the resource to remove the listener.<br/>
248 There exists also the `clear` member function to drop all the listeners at once.
250 Almost all the resources use to emit `ErrorEvent` events in case of errors.<br/>
251 All the other events are specific for the given resource and documented in the API reference.
253 The code below shows how to create a simple tcp server using `uvw`:
256 auto loop = uvw::Loop::getDefault();
257 auto tcp = loop.resource<uvw::TcpHandle>();
259 tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* something went wrong */ });
261 tcp->on<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TcpHandle &srv) {
262 std::shared_ptr<uvw::TcpHandle> client = srv.loop().resource<uvw::TcpHandle>();
263 client->once<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TcpHandle &client) { client.close(); });
264 client->on<uvw::DataEvent>([](const uvw::DataEvent &, uvw::TcpHandle &) { /* data received */ });
269 tcp->bind("127.0.0.1", 4242);
273 Note also that `uvw::TcpHandle` already supports _IPv6_ out-of-the-box. The statement above is equivalent to `tcp->bind<uvw::IPv4>("127.0.0.1", 4242)`.<br/>
274 It's suffice to explicitly specify `uvw::IPv6` as the underlying protocol to use it.
276 The API reference is the recommended documentation for further details about resources and their methods.
280 To compile and run the tests, `uvw` requires *libuv* and *googletest*.<br/>
281 `cmake` will download and compile both the libraries before to compile anything else.
292 If you want to contribute, please send patches as pull requests against the branch master.<br/>
293 Check the [contributors list](https://github.com/skypjack/uvw/blob/master/AUTHORS) to see who has partecipated so far.
295 # Projects that use `uvw`
297 Below an incomplete list of projects that use `uvw`:
299 * Internal tools (not publicly available) at **[Cynny SpA](https://www.morphcast.com/)** and **[Cynny Space](http://www.cynnyspace.com/)**.
300 * **[Calaos.fr](https://www.calaos.fr/en/)** (Open source home automation) on [GitHub](https://github.com/calaos).
301 * **[Iroha](http://iroha.tech/en/) - A simple, decentralized ledger** on [Github](https://github.com/hyperledger/iroha).
302 * **Iroha blockchain core** on [Github](https://github.com/finshield/iroha-core).
303 * **Ecwid Console Downloader** on [GitHub](https://github.com/dvetutnev/Ecwid-Console-downloader).
304 * **Simple network ping pong for lazy students** on [GitHub](https://github.com/dvetutnev/ping_pong).
306 If you know of other projects that use `libuv` through `uvw`, feel free to open a PR and I'll be glad to add them to the list.
310 Code and documentation Copyright (c) 2017 Michele Caini.<br/>
311 Code released under [the MIT license](https://github.com/skypjack/uvw/blob/master/LICENSE).<br/>
312 Docs released under [Creative Commons](https://github.com/skypjack/uvw/blob/master/docs/LICENSE).
316 The documentation is mostly inspired by the official [libuv API documentation](http://docs.libuv.org/en/v1.x/) for obvious reasons.<br/>
317 If you are mainly interested in the way `uvw` imports `libuv` in a `cmake` based project, I suggest you to take a look at [this](https://github.com/skypjack/libuv_cmake) repository instead.
321 Developing and maintaining `uvw` takes some time and lots of coffee. It still lacks a proper test suite, documentation is partially incomplete and not all functionalities have been fully implemented yet.<br/>
322 If you want to support this project, you can offer me an espresso. I'm from Italy, we're used to turning the best coffee ever in code.<br/>
323 Take a look at the donation button at the top of the page for more details or just click [here](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=W2HF9FESD5LJY&lc=IT&item_name=Michele%20Caini¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted).