uvw/index.html
2017-10-11 09:11:53 +02:00

235 lines
25 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>uvw: Main Page</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">uvw
&#160;<span id="projectnumber">1.3.0</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="headertitle">
<div class="title">uvw Documentation</div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="https://web.cynny.com/live/static/favicon/favicon-16.png" alt="cynny-logo"/>
</div>
<p> <b>Sponsored and contributed by <a href="https://www.cynny.com/">Cynny SpA</a>.</b></p>
<h1>uvw - libuv wrapper in modern C++</h1>
<p><a href="https://travis-ci.org/skypjack/uvw"></a> <a href="https://ci.appveyor.com/project/skypjack/uvw"></a> <a href="https://coveralls.io/github/skypjack/uvw?branch=master"></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=W2HF9FESD5LJY&amp;lc=IT&amp;item_name=Michele%20Caini&amp;currency_code=EUR&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"></a></p>
<h1>Introduction</h1>
<p><code>uvw</code> is a header-only, event based, tiny and easy to use <em>libuv</em> wrapper in modern C++.<br />
The basic idea is to hide completely the <em>C-ish</em> interface of <em>libuv</em> behind a graceful C++ API. Currently, no <code>uv_*_t</code> data structure is actually exposed by the library.<br />
Note that <code>uvw</code> stays true to the API of <em>libuv</em> 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 <em>libuv</em>.<br />
As an example, a <em>handle</em> should be initialized before any other operation and closed once it is no longer in use.</p>
<h2>Code Example</h2>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;uvw.hpp&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;memory&gt;</span></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> listen(<a class="code" href="classuvw_1_1Loop.html">uvw::Loop</a> &amp;loop) {</div><div class="line"> std::shared_ptr&lt;uvw::TcpHandle&gt; tcp = loop.<a class="code" href="classuvw_1_1Loop.html#a3898884e2019aa052235377dcd03c0f3">resource</a>&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div><div class="line"></div><div class="line"> tcp-&gt;<a class="code" href="classuvw_1_1Emitter.html#a79e4ed59b5bb5cdc5ee4b0dd71a38472">once</a>&lt;<a class="code" href="structuvw_1_1ListenEvent.html">uvw::ListenEvent</a>&gt;([](<span class="keyword">const</span> <a class="code" href="structuvw_1_1ListenEvent.html">uvw::ListenEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;srv) {</div><div class="line"> std::shared_ptr&lt;uvw::TcpHandle&gt; client = srv.loop().resource&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div><div class="line"></div><div class="line"> client-&gt;<a class="code" href="classuvw_1_1Emitter.html#af6ba3eecb542efbef8d62ae905d8a8cd">on</a>&lt;<a class="code" href="structuvw_1_1CloseEvent.html">uvw::CloseEvent</a>&gt;([ptr = srv.shared_from_this()](<span class="keyword">const</span> <a class="code" href="structuvw_1_1CloseEvent.html">uvw::CloseEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;) { ptr-&gt;close(); });</div><div class="line"> client-&gt;on&lt;<a class="code" href="structuvw_1_1EndEvent.html">uvw::EndEvent</a>&gt;([](<span class="keyword">const</span> <a class="code" href="structuvw_1_1EndEvent.html">uvw::EndEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;client) { client.close(); });</div><div class="line"></div><div class="line"> srv.accept(*client);</div><div class="line"> client-&gt;read();</div><div class="line"> });</div><div class="line"></div><div class="line"> tcp-&gt;bind(<span class="stringliteral">&quot;127.0.0.1&quot;</span>, 4242);</div><div class="line"> tcp-&gt;listen();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> conn(<a class="code" href="classuvw_1_1Loop.html">uvw::Loop</a> &amp;loop) {</div><div class="line"> <span class="keyword">auto</span> tcp = loop.<a class="code" href="classuvw_1_1Loop.html#a3898884e2019aa052235377dcd03c0f3">resource</a>&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div><div class="line"></div><div class="line"> tcp-&gt;<a class="code" href="classuvw_1_1Emitter.html#af6ba3eecb542efbef8d62ae905d8a8cd">on</a>&lt;<a class="code" href="structuvw_1_1ErrorEvent.html">uvw::ErrorEvent</a>&gt;([](<span class="keyword">const</span> <a class="code" href="structuvw_1_1ErrorEvent.html">uvw::ErrorEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;) { <span class="comment">/* handle errors */</span> });</div><div class="line"></div><div class="line"> tcp-&gt;once&lt;<a class="code" href="structuvw_1_1ConnectEvent.html">uvw::ConnectEvent</a>&gt;([](<span class="keyword">const</span> <a class="code" href="structuvw_1_1ConnectEvent.html">uvw::ConnectEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;tcp) {</div><div class="line"> <span class="keyword">auto</span> dataWrite = std::unique_ptr&lt;char[]&gt;(<span class="keyword">new</span> <span class="keywordtype">char</span>[2]{ <span class="charliteral">&#39;b&#39;</span>, <span class="charliteral">&#39;c&#39;</span> });</div><div class="line"> tcp.write(std::move(dataWrite), 2);</div><div class="line"> tcp.close();</div><div class="line"> });</div><div class="line"></div><div class="line"> tcp-&gt;connect(std::string{<span class="stringliteral">&quot;127.0.0.1&quot;</span>}, 4242);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() {</div><div class="line"> <span class="keyword">auto</span> loop = <a class="code" href="classuvw_1_1Loop.html#a284450b3ef37c62bd7a984c73552d7b8">uvw::Loop::getDefault</a>();</div><div class="line"> listen(*loop);</div><div class="line"> conn(*loop);</div><div class="line"> loop-&gt;<a class="code" href="classuvw_1_1Loop.html#aa86d06ae9f91d8b48d1d5358040f2547">run</a>();</div><div class="line">}</div></div><!-- fragment --><h2>Motivation</h2>
<p>The main reason for which <code>uvw</code> has been written is the fact that it does not exist a valid <em>libuv</em> wrapper in C++. That's all.</p>
<h1>Build Instructions</h1>
<h2>Requirements</h2>
<p>To be able to use <code>uvw</code>, users must provide the following system-wide tools:</p>
<ul>
<li>A full-featured compiler that supports at least C++14.</li>
<li><code>libuv</code> (which version depends on the tag of <code>uvw</code> in use).</li>
</ul>
<p>The requirements below are mandatory to compile the tests and to extract the documentation:</p>
<ul>
<li>CMake version 3.2 or later.</li>
<li>Doxygen version 1.8 or later.</li>
</ul>
<p>Note that <code>libuv</code> is part of the dependencies of the project and it will be cloned by <code>cmake</code> (see below for further details).<br />
Because of that, users have not to install it to compile and execute the tests.</p>
<h2>Library</h2>
<p><code>uvw</code> is a header-only library.<br />
This means that including the <code><a class="el" href="uvw_8hpp_source.html">uvw.hpp</a></code> header or one of the other <code>uvw/*.hpp</code> headers is enough to use it.<br />
It's a matter of adding the following line at the top of a file:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;uvw.hpp&gt;</span></div></div><!-- fragment --><p>Then pass the proper <code>-I</code> argument to the compiler to add the <code>src</code> directory to the include paths.<br />
Note that users are demanded to correctly setup include directories and libraries search paths for <em>libuv</em>.</p>
<h2>Versioning</h2>
<p>Starting with tag <em>v1.12.0</em> of <code>libuv</code>, <code>uvw</code> follows the <a href="http://semver.org/">semantic versioning</a> scheme.<br />
The problem is that any version of <code>uvw</code> also requires to track explicitly the version of <code>libuv</code> to which it is bound.<br />
Because of that, the latter wil be appended to the version of <code>uvw</code>. As an example: </p><pre class="fragment">vU.V.W_libuv-vX.Y
</pre><p>In particular, the following applies:</p>
<ul>
<li><em>U.V.W</em> are major, minor and patch versions of <code>uvw</code>.</li>
<li><em>X.Y</em> is the version of <code>libuv</code> to which to refer (where any patch version is valid).</li>
</ul>
<p>In other terms, tags will look like this from now on: </p><pre class="fragment">v1.0.0_libuv-v1.12
</pre><p>Branch <code>master</code> of <code>uvw</code> will be a work in progress branch that follows branch <em>v1.x</em> of <code>libuv</code> (at least as long as it remains their <em>master</em> branch).<br />
</p>
<h2>Documentation</h2>
<h3>API Reference</h3>
<p>The documentation is based on <a href="http://www.stack.nl/~dimitri/doxygen/"><code>doxygen</code></a>. To build it:</p>
<ul>
<li><code>$ cd build</code></li>
<li><code>$ cmake ..</code></li>
<li><code>$ make docs</code></li>
</ul>
<p>The API reference will be created in HTML format within the directory <code>build/docs/html</code>.<br />
To navigate it with your favorite browser:</p>
<ul>
<li><code>$ cd build</code></li>
<li><code>$ your_favorite_browser docs/html/index.html</code></li>
</ul>
<h3>Crash Course</h3>
<h4>Vademecum</h4>
<p>There is only one rule when using <code>uvw</code>: always initialize the resources and terminate them.</p>
<p>Resources belong mainly to two families: <em>handles</em> and <em>requests</em>.<br />
Handles represent long-lived objects capable of performing certain operations while active.<br />
Requests represent (typically) short-lived operations performed either over a handle or standalone.</p>
<p>The following sections will explain in short what it means to initialize and terminate these kinds of resources.</p>
<h4>Handles</h4>
<p>Initialization is usually performed under the hood and can be even passed over, as far as handles are created using the <code>Loop::resource</code> member function.<br />
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 />
Therefore the rule quickly becomes <em>always close your handles</em>. It's as simple as calling the <code>close</code> member function on them.</p>
<h4>Requests</h4>
<p>Usually initializing a request object is not required. Anyway, the recommended way to create a request is still through the <code>Loop::resource</code> member function.<br />
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 />
Therefore the rule quickly becomes <em>feel free to make a request and forget about it</em>. It's as simple as calling a member function on them.</p>
<h4>The Loop and the Resource</h4>
<p>The first thing to do to use <code>uvw</code> is to create a loop. In case the default one is enough, it's easy as doing this:</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> loop = <a class="code" href="classuvw_1_1Loop.html#a284450b3ef37c62bd7a984c73552d7b8">uvw::Loop::getDefault</a>();</div></div><!-- fragment --><p>Note that loop objects don't require to be closed explicitly, even if they offer the <code>close</code> member function in case an user wants to do that.<br />
Loops can be started using the <code>run</code> member function. The two calls below are equivalent:</p>
<div class="fragment"><div class="line">loop-&gt;<a class="code" href="classuvw_1_1Loop.html#aa86d06ae9f91d8b48d1d5358040f2547">run</a>();</div><div class="line">loop-&gt;<a class="code" href="classuvw_1_1Loop.html#aa86d06ae9f91d8b48d1d5358040f2547">run</a>&lt;uvw::Loop::Mode::DEFAULT&gt;</div></div><!-- fragment --><p>Available modes are: <code>DEFAULT</code>, <code>ONCE</code>, <code>NOWAIT</code>. Please refer to the documentation of <em>libuv</em> for further details.</p>
<p>In order to create a resource and to bind it to the given loop, just do the following:</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> tcp = loop.<a class="code" href="classuvw_1_1Loop.html#a3898884e2019aa052235377dcd03c0f3">resource</a>&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div></div><!-- fragment --><p>The line above will create and initialize a tcp handle, then a shared pointer to that resource will be returned.<br />
Users should check if pointers have been correctly initialized: in case of errors, they won't be.<br />
Another way to create a resource is:</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> tcp = TcpHandle::create(loop);</div><div class="line">tcp-&gt;init();</div></div><!-- fragment --><p>Pretty annoying indeed. Using a loop is the recommended approach.</p>
<p>The resources also accept arbitrary user-data that won't be touched in any case.<br />
Users can set and get them through the <code>data</code> member function as it follows:</p>
<div class="fragment"><div class="line">resource-&gt;data(std::make_shared&lt;int&gt;(42));</div><div class="line">std::shared_ptr&lt;void&gt; data = resource-&gt;data();</div></div><!-- fragment --><p>Resources expect a <code>std::shared_pointer&lt;void&gt;</code> and return it, therefore any kind of data is welcome.<br />
Users can explicitly specify a type other than <code>void</code> when calling the <code>data</code> member function:</p>
<div class="fragment"><div class="line">std::shared_ptr&lt;int&gt; data = resource-&gt;data&lt;<span class="keywordtype">int</span>&gt;();</div></div><!-- fragment --><p>Remember from the previous section that a handle will keep itself alive until one invokes the <code>close</code> member function on it.<br />
To know what are the handles that are still alive and bound to a given loop, just do the following:</p>
<div class="fragment"><div class="line">loop.<a class="code" href="classuvw_1_1Loop.html#a699f41c1c1d31a65c5d12adacdbb94e1">walk</a>([](<a class="code" href="structuvw_1_1BaseHandle.html">uvw::BaseHandle</a> &amp;){ <span class="comment">/* application code here */</span> });</div></div><!-- fragment --><p><code>BaseHandle</code> exposes a few methods and cannot be promoted to the original type of the handle (even though <code>type</code> and <code>category</code> member functions fill the gap somehow).<br />
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:</p>
<div class="fragment"><div class="line">loop.<a class="code" href="classuvw_1_1Loop.html#a699f41c1c1d31a65c5d12adacdbb94e1">walk</a>([](<a class="code" href="structuvw_1_1BaseHandle.html">uvw::BaseHandle</a> &amp;h){ h.<a class="code" href="structuvw_1_1BaseHandle.html#a83b88fc17d491e48e4c519c9551ab0b4">close</a>(); });</div></div><!-- fragment --><p>No need to keep track of them.</p>
<p>To know what are the available resources' types, please refer the API reference.</p>
<h4>The event-based approach</h4>
<p>For <code>uvw</code> offers an event-based approach, resources are small event emitters to which listeners can be attached.<br />
Attaching a listener to a resource is the recommended way to be notified about changes.<br />
Listeners must be callable objects of type <code>void(EventType &amp;, ResourceType &amp;)</code>, where:</p>
<ul>
<li><code>EventType</code> is the type of the event for which they have been designed.</li>
<li><code>ResourceType</code> is the type of the resource that has originated the event.</li>
</ul>
<p>It means that the following function types are all valid:</p>
<ul>
<li><code>void(EventType &amp;, ResourceType &amp;)</code></li>
<li><code>void(const EventType &amp;, ResourceType &amp;)</code></li>
<li><code>void(EventType &amp;, const ResourceType &amp;)</code></li>
<li><code>void(const EventType &amp;, const ResourceType &amp;)</code></li>
</ul>
<p>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.</p>
<p>There exist two methods to attach an event to a resource:</p>
<ul>
<li><code>resource.once&lt;EventType&gt;(listener)</code>: the listener will be automatically removed after the first event of the given type.</li>
<li><code>resource.on&lt;EventType&gt;(listener)</code>: to be used for long-running listeners.</li>
</ul>
<p>Both of them return an object of type <code>ResourceType::Connection</code> (as an example, <code>TcpHandle::Connection</code>).<br />
A connection object can be used later as an argument to the <code>erase</code> member function of the resource to remove the listener.<br />
There exists also the <code>clear</code> member function to drop all the listeners at once.</p>
<p>Almost all the resources use to emit <code>ErrorEvent</code> events in case of errors.<br />
All the other events are specific for the given resource and documented in the API reference.</p>
<p>The code below shows how to create a simple tcp server using <code>uvw</code>:</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> loop = <a class="code" href="classuvw_1_1Loop.html#a284450b3ef37c62bd7a984c73552d7b8">uvw::Loop::getDefault</a>();</div><div class="line"><span class="keyword">auto</span> tcp = loop.<a class="code" href="classuvw_1_1Loop.html#a3898884e2019aa052235377dcd03c0f3">resource</a>&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div><div class="line"></div><div class="line">tcp-&gt;<a class="code" href="classuvw_1_1Emitter.html#af6ba3eecb542efbef8d62ae905d8a8cd">on</a>&lt;uvw::ErrorEvent&gt;([](<span class="keyword">const</span> uvw::ErrorEvent &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;) { <span class="comment">/* something went wrong */</span> });</div><div class="line"></div><div class="line">tcp-&gt;on&lt;uvw::ListenEvent&gt;([](<span class="keyword">const</span> uvw::ListenEvent &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;srv) {</div><div class="line"> std::shared_ptr&lt;uvw::TcpHandle&gt; client = srv.loop().resource&lt;<a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a>&gt;();</div><div class="line"> client-&gt;<a class="code" href="classuvw_1_1Emitter.html#a79e4ed59b5bb5cdc5ee4b0dd71a38472">once</a>&lt;uvw::EndEvent&gt;([](<span class="keyword">const</span> uvw::EndEvent &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;client) { client.close(); });</div><div class="line"> client-&gt;on&lt;<a class="code" href="structuvw_1_1DataEvent.html">uvw::DataEvent</a>&gt;([](<span class="keyword">const</span> <a class="code" href="structuvw_1_1DataEvent.html">uvw::DataEvent</a> &amp;, <a class="code" href="classuvw_1_1TcpHandle.html">uvw::TcpHandle</a> &amp;) { <span class="comment">/* data received */</span> });</div><div class="line"> srv.accept(*client);</div><div class="line"> client-&gt;read();</div><div class="line">});</div><div class="line"></div><div class="line">tcp-&gt;bind(<span class="stringliteral">&quot;127.0.0.1&quot;</span>, 4242);</div><div class="line">tcp-&gt;listen();</div></div><!-- fragment --><p>Note also that <code><a class="el" href="classuvw_1_1TcpHandle.html" title="The TcpHandle handle. ">uvw::TcpHandle</a></code> already supports <em>IPv6</em> out-of-the-box. The statement above is equivalent to <code>tcp-&gt;bind&lt;<a class="el" href="structuvw_1_1IPv4.html" title="The IPv4 tag. ">uvw::IPv4</a>&gt;("127.0.0.1", 4242)</code>.<br />
It's suffice to explicitly specify <code><a class="el" href="structuvw_1_1IPv6.html" title="The IPv6 tag. ">uvw::IPv6</a></code> as the underlying protocol to use it.</p>
<p>The API reference is the recommended documentation for further details about resources and their methods.</p>
<h2>Tests</h2>
<p>To compile and run the tests, <code>uvw</code> requires <em>libuv</em> and <em>googletest</em>.<br />
<code>cmake</code> will download and compile both the libraries before to compile anything else.</p>
<p>To build the tests:</p>
<ul>
<li><code>$ cd build</code></li>
<li><code>$ cmake ..</code></li>
<li><code>$ make</code></li>
<li><code>$ make test</code></li>
</ul>
<h1>Contributors</h1>
<p>If you want to contribute, please send patches as pull requests against the branch master.<br />
Check the <a href="https://github.com/skypjack/uvw/blob/master/AUTHORS">contributors list</a> to see who has partecipated so far.</p>
<h1>Projects that use <code>uvw</code></h1>
<p>Below an incomplete list of projects that use <code>uvw</code>:</p>
<ul>
<li>Internal tools (not publicly available) at <b><a href="https://www.morphcast.com/">Cynny SpA</a></b> and <b><a href="http://www.cynnyspace.com/">Cynny Space</a></b>.</li>
<li><b><a href="https://www.calaos.fr/en/">Calaos.fr</a></b> (Open source home automation) on <a href="https://github.com/calaos">GitHub</a>.</li>
<li><b><a href="http://iroha.tech/en/">Iroha</a> - A simple, decentralized ledger</b> on <a href="https://github.com/hyperledger/iroha">Github</a>.</li>
<li><b>Iroha blockchain core</b> on <a href="https://github.com/finshield/iroha-core">Github</a>.</li>
<li><b>Ecwid Console Downloader</b> on <a href="https://github.com/dvetutnev/Ecwid-Console-downloader">GitHub</a>.</li>
<li><b>Simple network ping pong for lazy students</b> on <a href="https://github.com/dvetutnev/ping_pong">GitHub</a>.</li>
</ul>
<p>If you know of other projects that use <code>libuv</code> through <code>uvw</code>, feel free to open a PR and I'll be glad to add them to the list.</p>
<h1>License</h1>
<p>Code and documentation Copyright (c) 2017 Michele Caini.<br />
Code released under <a href="https://github.com/skypjack/uvw/blob/master/LICENSE">the MIT license</a>.<br />
Docs released under <a href="https://github.com/skypjack/uvw/blob/master/docs/LICENSE">Creative Commons</a>.</p>
<h1>Note</h1>
<p>The documentation is mostly inspired by the official <a href="http://docs.libuv.org/en/v1.x/">libuv API documentation</a> for obvious reasons.<br />
If you are mainly interested in the way <code>uvw</code> imports <code>libuv</code> in a <code>cmake</code> based project, I suggest you to take a look at <a href="https://github.com/skypjack/libuv_cmake">this</a> repository instead.</p>
<h1>Donation</h1>
<p>Developing and maintaining <code>uvw</code> 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 />
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 />
Take a look at the donation button at the top of the page for more details or just click <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=W2HF9FESD5LJY&amp;lc=IT&amp;item_name=Michele%20Caini&amp;currency_code=EUR&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">here</a>. </p>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
</body>
</html>