uvw  1.3.0
README.md
1 ![cynny-logo](https://web.cynny.com/live/static/favicon/favicon-16.png) **Sponsored and contributed by [Cynny SpA](https://www.cynny.com/).**
2 
3 # uvw - libuv wrapper in modern C++
4 
5 [![Build Status](https://travis-ci.org/skypjack/uvw.svg?branch=master)](https://travis-ci.org/skypjack/uvw)
6 [![Build status](https://ci.appveyor.com/api/projects/status/m5ndm8gnu8isg2to?svg=true)](https://ci.appveyor.com/project/skypjack/uvw)
7 [![Coverage Status](https://coveralls.io/repos/github/skypjack/uvw/badge.svg?branch=master)](https://coveralls.io/github/skypjack/uvw?branch=master)
8 [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=W2HF9FESD5LJY&lc=IT&item_name=Michele%20Caini&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)
9 
10 # Introduction
11 
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.
16 
17 ## Code Example
18 
19 ```cpp
20 #include <uvw.hpp>
21 #include <memory>
22 
23 void listen(uvw::Loop &loop) {
24  std::shared_ptr<uvw::TcpHandle> tcp = loop.resource<uvw::TcpHandle>();
25 
26  tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TcpHandle &srv) {
27  std::shared_ptr<uvw::TcpHandle> client = srv.loop().resource<uvw::TcpHandle>();
28 
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(); });
31 
32  srv.accept(*client);
33  client->read();
34  });
35 
36  tcp->bind("127.0.0.1", 4242);
37  tcp->listen();
38 }
39 
40 void conn(uvw::Loop &loop) {
41  auto tcp = loop.resource<uvw::TcpHandle>();
42 
43  tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* handle errors */ });
44 
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);
48  tcp.close();
49  });
50 
51  tcp->connect(std::string{"127.0.0.1"}, 4242);
52 }
53 
54 int main() {
55  auto loop = uvw::Loop::getDefault();
56  listen(*loop);
57  conn(*loop);
58  loop->run();
59 }
60 ```
61 
62 ## Motivation
63 
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.
65 
66 # Build Instructions
67 
68 ## Requirements
69 
70 To be able to use `uvw`, users must provide the following system-wide tools:
71 
72 * A full-featured compiler that supports at least C++14.
73 * `libuv` (which version depends on the tag of `uvw` in use).
74 
75 The requirements below are mandatory to compile the tests and to extract the documentation:
76 
77 * CMake version 3.2 or later.
78 * Doxygen version 1.8 or later.
79 
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.
82 
83 ## Library
84 
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:
88 
89 ```cpp
90 #include <uvw.hpp>
91 ```
92 
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*.
95 
96 ## Versioning
97 
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:
101 
102  vU.V.W_libuv-vX.Y
103 
104 In particular, the following applies:
105 
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).
108 
109 In other terms, tags will look like this from now on:
110 
111  v1.0.0_libuv-v1.12
112 
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/>
114 
115 ## Documentation
116 
117 ### API Reference
118 
119 The documentation is based on [`doxygen`](http://www.stack.nl/~dimitri/doxygen/). To build it:
120 
121 * `$ cd build`
122 * `$ cmake ..`
123 * `$ make docs`
124 
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:
127 
128 * `$ cd build`
129 * `$ your_favorite_browser docs/html/index.html`
130 
131 ### Crash Course
132 
133 #### Vademecum
134 
135 There is only one rule when using `uvw`: always initialize the resources and terminate them.
136 
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.
140 
141 The following sections will explain in short what it means to initialize and terminate these kinds of resources.
142 
143 #### Handles
144 
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.
148 
149 #### Requests
150 
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.
154 
155 #### The Loop and the Resource
156 
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:
158 
159 ```cpp
160 auto loop = uvw::Loop::getDefault();
161 ```
162 
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:
165 
166 ```cpp
167 loop->run();
168 loop->run<uvw::Loop::Mode::DEFAULT>
169 ```
170 
171 Available modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the documentation of *libuv* for further details.
172 
173 In order to create a resource and to bind it to the given loop, just do the following:
174 
175 ```cpp
176 auto tcp = loop.resource<uvw::TcpHandle>();
177 ```
178 
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:
182 
183 ```cpp
184 auto tcp = TcpHandle::create(loop);
185 tcp->init();
186 ```
187 
188 Pretty annoying indeed. Using a loop is the recommended approach.
189 
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:
192 
193 ```cpp
194 resource->data(std::make_shared<int>(42));
195 std::shared_ptr<void> data = resource->data();
196 ```
197 
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:
200 
201 ```cpp
202 std::shared_ptr<int> data = resource->data<int>();
203 ```
204 
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:
207 
208 ```cpp
209 loop.walk([](uvw::BaseHandle &){ /* application code here */ });
210 ```
211 
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:
214 
215 ```cpp
216 loop.walk([](uvw::BaseHandle &h){ h.close(); });
217 ```
218 
219 No need to keep track of them.
220 
221 To know what are the available resources' types, please refer the API reference.
222 
223 #### The event-based approach
224 
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:
228 
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.
231 
232 It means that the following function types are all valid:
233 
234 * `void(EventType &, ResourceType &)`
235 * `void(const EventType &, ResourceType &)`
236 * `void(EventType &, const ResourceType &)`
237 * `void(const EventType &, const ResourceType &)`
238 
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.
240 
241 There exist two methods to attach an event to a resource:
242 
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.
245 
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.
249 
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.
252 
253 The code below shows how to create a simple tcp server using `uvw`:
254 
255 ```cpp
256 auto loop = uvw::Loop::getDefault();
257 auto tcp = loop.resource<uvw::TcpHandle>();
258 
259 tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* something went wrong */ });
260 
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 */ });
265  srv.accept(*client);
266  client->read();
267 });
268 
269 tcp->bind("127.0.0.1", 4242);
270 tcp->listen();
271 ```
272 
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.
275 
276 The API reference is the recommended documentation for further details about resources and their methods.
277 
278 ## Tests
279 
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.
282 
283 To build the tests:
284 
285 * `$ cd build`
286 * `$ cmake ..`
287 * `$ make`
288 * `$ make test`
289 
290 # Contributors
291 
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.
294 
295 # Projects that use `uvw`
296 
297 Below an incomplete list of projects that use `uvw`:
298 
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).
305 
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.
307 
308 # License
309 
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).
313 
314 # Note
315 
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.
318 
319 # Donation
320 
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&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted).