{"id":13418905,"url":"https://github.com/skypjack/uvw","last_synced_at":"2025-05-14T00:07:28.503Z","repository":{"id":9288545,"uuid":"61499901","full_name":"skypjack/uvw","owner":"skypjack","description":"Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!","archived":false,"fork":false,"pushed_at":"2025-04-09T08:36:28.000Z","size":16220,"stargazers_count":1931,"open_issues_count":9,"forks_count":221,"subscribers_count":64,"default_branch":"main","last_synced_at":"2025-05-10T11:04:14.287Z","etag":null,"topics":["cpp","cpp17","event-loop","header-only","libuv","modern-cpp","uvw","wrapper"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skypjack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"skypjack","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://www.paypal.me/skypjack"}},"created_at":"2016-06-19T20:53:34.000Z","updated_at":"2025-05-09T23:46:17.000Z","dependencies_parsed_at":"2024-02-06T10:25:21.020Z","dependency_job_id":"23df5dec-5de3-4d3a-b8a1-04dfa7e3bc78","html_url":"https://github.com/skypjack/uvw","commit_stats":{"total_commits":749,"total_committers":30,"mean_commits":"24.966666666666665","dds":"0.14552736982643522","last_synced_commit":"6d771874a89eb4c6399b902c743c9a2333f803c3"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skypjack%2Fuvw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skypjack%2Fuvw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skypjack%2Fuvw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skypjack%2Fuvw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skypjack","download_url":"https://codeload.github.com/skypjack/uvw/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253405022,"owners_count":21903113,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp17","event-loop","header-only","libuv","modern-cpp","uvw","wrapper"],"created_at":"2024-07-30T22:01:08.668Z","updated_at":"2025-05-14T00:07:28.469Z","avatar_url":"https://github.com/skypjack.png","language":"C++","readme":"![uvw - libuv wrapper in modern C++](https://user-images.githubusercontent.com/1812216/46069406-c977a600-c17b-11e8-9a47-9bba6f412c57.png)\n\n[![Build Status](https://github.com/skypjack/uvw/workflows/build/badge.svg)](https://github.com/skypjack/uvw/actions)\n[![Coverage](https://codecov.io/gh/skypjack/uvw/branch/master/graph/badge.svg)](https://codecov.io/gh/skypjack/uvw)\n[![Documentation](https://img.shields.io/badge/docs-doxygen-blue)](https://skypjack.github.io/uvw/)\n[![Vcpkg port](https://img.shields.io/vcpkg/v/uvw)](https://vcpkg.link/ports/uvw)\n[![Gitter chat](https://badges.gitter.im/skypjack/uvw.png)](https://gitter.im/skypjack/uvw)\n[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/skypjack)\n\nDo you have a **question** that doesn't require you to open an issue? Join the\n[gitter channel](https://gitter.im/skypjack/uvw).\u003cbr/\u003e\nIf you use `uvw` and you want to say thanks or support the project, please\n**consider becoming a\n[sponsor](https://github.com/users/skypjack/sponsorship)**.\u003cbr/\u003e\nYou can help me make the difference.\n[Many thanks](https://skypjack.github.io/sponsorship/) to those who supported me\nand still support me today.\n\n# Introduction\n\n`uvw` started as a header-only, event based, tiny and easy to use wrapper for\n[`libuv`](https://github.com/libuv/libuv) written in modern C++.\u003cbr/\u003e\nNow it's finally available also as a compilable static library.\n\nThe basic idea is to wrap the *C-ish* interface of `libuv` behind a graceful C++\nAPI.\u003cbr/\u003e\nNote that `uvw` stays true to the API of `libuv` and it doesn't add anything to\nits interface. For the same reasons, users of the library must follow the same\nrules which are used with `libuv`.\u003cbr/\u003e\nAs an example, a *handle* should be initialized before any other operation and\nclosed once it is no longer in use.\n\n## Code Example\n\n```cpp\n#include \u003cuvw.hpp\u003e\n#include \u003cmemory\u003e\n\nvoid listen(uvw::loop \u0026loop) {\n    std::shared_ptr\u003cuvw::tcp_handle\u003e tcp = loop.resource\u003cuvw::tcp_handle\u003e();\n\n    tcp-\u003eon\u003cuvw::listen_event\u003e([](const uvw::listen_event \u0026, uvw::tcp_handle \u0026srv) {\n        std::shared_ptr\u003cuvw::tcp_handle\u003e client = srv.parent().resource\u003cuvw::tcp_handle\u003e();\n\n        client-\u003eon\u003cuvw::close_event\u003e([ptr = srv.shared_from_this()](const uvw::close_event \u0026, uvw::tcp_handle \u0026) { ptr-\u003eclose(); });\n        client-\u003eon\u003cuvw::end_event\u003e([](const uvw::end_event \u0026, uvw::tcp_handle \u0026client) { client.close(); });\n\n        srv.accept(*client);\n        client-\u003eread();\n    });\n\n    tcp-\u003ebind(\"127.0.0.1\", 4242);\n    tcp-\u003elisten();\n}\n\nvoid conn(uvw::loop \u0026loop) {\n    auto tcp = loop.resource\u003cuvw::tcp_handle\u003e();\n\n    tcp-\u003eon\u003cuvw::error_event\u003e([](const uvw::error_event \u0026, uvw::tcp_handle \u0026) { /* handle errors */ });\n\n    tcp-\u003eon\u003cuvw::connect_event\u003e([](const uvw::connect_event \u0026, uvw::tcp_handle \u0026tcp) {\n        auto dataWrite = std::unique_ptr\u003cchar[]\u003e(new char[2]{ 'b', 'c' });\n        tcp.write(std::move(dataWrite), 2);\n        tcp.close();\n    });\n\n    tcp-\u003econnect(std::string{\"127.0.0.1\"}, 4242);\n}\n\nint main() {\n    auto loop = uvw::loop::get_default();\n    listen(*loop);\n    conn(*loop);\n    loop-\u003erun();\n}\n```\n\n## Motivation\n\nThe main reason for which `uvw` has been written is the fact that there does not\nexist a valid `libuv` wrapper in C++. That's all.\n\n# Build Instructions\n\n## Requirements\n\nTo be able to use `uvw`, users must provide the following system-wide tools:\n\n* A full-featured compiler that supports at least C++17.\n* `libuv` (which version depends on the tag of `uvw` in use)\n  *  If you use `meson`, libuv will be downloaded for you\n\nThe requirements below are mandatory to compile the tests and to extract the\ndocumentation:\n\n* CMake version 3.13 or later.\n* Doxygen version 1.8 or later.\n\nNote that `libuv` is part of the dependencies of the project and may be cloned\nby `CMake` in some cases (see below for further details).\u003cbr/\u003e\nBecause of that, users don't have to install it to run the tests or when `uvw`\nlibraries are compiled through `CMake`.\n\n## Meson\n\nYou can use `uvw` with [meson](https://mesonbuild.com/) by simply adding it to\nyour `subprojects` directory in your project.\n\nTo compile `uvw` from source without using it as a subproject, in the `uvw`\nsource directory, run:\n\n* `$ meson setup build`\n  * If you want a static library, add `--default-library=static`\n* `$ cd build`\n* `$ meson compile`\n\n## Library\n\n`uvw` is a dual-mode library. It can be used in its header-only form or as a\ncompiled static library.\u003cbr/\u003e\nThe following sections describe what to do in both cases to get `uvw` up and\nrunningin your own project.\n\n### Header-only\n\nTo use `uvw` as a header-only library, all is needed is to include the `uvw.hpp`\nheader or one of the other `uvw/*.hpp` files.\u003cbr/\u003e\nIt's a matter of adding the following line at the top of a file:\n\n```cpp\n#include \u003cuvw.hpp\u003e\n```\n\nThen pass the proper `-I` argument to the compiler to add the `src` directory to\nthe include paths.\u003cbr/\u003e\nNote that users are required to correctly setup the include directories and\nlibraries search paths for `libuv` in this case.\n\nWhen used through `CMake`, the `uvw::uvw` target is exported for convenience.\n\n### Static\n\nTo use `uvw` as a compiled library, set the `UVW_BUILD_LIBS` options in cmake\nbefore including the project.\u003cbr/\u003e\nThis option triggers the generation of a targets named\n`uvw::uvw-static`. The matching version of `libuv` is also\ncompiled and exported as `uv::uv-static` for convenience.\n\nIn case you don't use or don't want to use `CMake`, you can still compile all\n`.cpp` files and include all `.h` files to get the job done. In this case, users\nare required to correctly setup the include directories and libraries search\npaths for `libuv`.\n\n## Versioning\n\nStarting with tag _v1.12.0_ of `libuv`, `uvw` follows the\n[semantic versioning](http://semver.org/) scheme.\u003cbr/\u003e\nThe problem is that any version of `uvw` also requires to track explicitly the\nversion of `libuv` to which it is bound.\u003cbr/\u003e\nBecause of that, the latter wil be appended to the version of `uvw`. As an\nexample:\n\n    vU.V.W_libuv-vX.Y\n\nIn particular, the following applies:\n\n* _U.V.W_ are major, minor and patch versions of `uvw`.\n* _X.Y_ is the version of `libuv` to which to refer (where any patch version is\n  valid).\n\nIn other terms, tags will look like this from now on:\n\n    v1.0.0_libuv-v1.12\n\nBranch `master` of `uvw` will be a work in progress branch that follows branch\n_v1.x_ of `libuv` (at least as long as it remains their _master_ branch).\u003cbr/\u003e\n\n## Documentation\n\nThe documentation is based on\n[`doxygen`](https://www.doxygen.nl/). To build it:\n\n* `$ cd build`\n* `$ cmake ..`\n* `$ make docs`\n\nThe API reference will be created in HTML format within the directory\n`build/docs/html`.\u003cbr/\u003e\nTo navigate it with your favorite browser:\n\n* `$ cd build`\n* `$ your_favorite_browser docs/html/index.html`\n\nThe same version is also available [online](https://skypjack.github.io/uvw/)\nfor the latest release, that is the last stable tag.\n\n### Note\n\nThe documentation is mostly inspired by the official\n[libuv API documentation](http://docs.libuv.org/en/v1.x/) for obvious\nreasons.\n\n## Tests\n\nTo compile and run the tests, `uvw` requires `libuv` and `googletest`.\u003cbr/\u003e\n`CMake` will download and compile both the libraries before compiling anything\nelse.\n\nTo build the tests:\n\n* `$ cd build`\n* `$ cmake .. -DUVW_BUILD_TESTING=ON`\n* `$ make`\n* `$ ctest -j4 -R uvw`\n\nOmit `-R uvw` if you also want to test `libuv` and other dependencies.\n\n# Crash Course\n\n## Vademecum\n\nThere is only one rule when using `uvw`: always initialize the resources and\nterminate them.\n\nResources belong mainly to two families: _handles_ and _requests_.\u003cbr/\u003e\nHandles represent long-lived objects capable of performing certain operations\nwhile active.\u003cbr/\u003e\nRequests represent (typically) short-lived operations performed either over a\nhandle or standalone.\n\nThe following sections will explain in short what it means to initialize and\nterminate these kinds of resources.\u003cbr/\u003e\nFor more details, please refer to the\n[online documentation](https://skypjack.github.io/uvw/).\n\n## Handles\n\nInitialization is usually performed under the hood and can be even passed over,\nas far as handles are created using the `loop::resource` member function.\u003cbr/\u003e\nOn the other side, handles keep themselves alive until one explicitly closes\nthem. Because of that, memory usage will grow if users simply forget about a\nhandle.\u003cbr/\u003e\nTherefore the rule quickly becomes *always close your handles*. It's as simple\nas calling the `close` member function on them.\n\n## Requests\n\nUsually initializing a request object is not required. Anyway, the recommended\nway to create a request is still through the `loop::resource` member\nfunction.\u003cbr/\u003e\nRequests will keep themselves alive as long as they are bound to unfinished\nunderlying activities. This means that users don't have to discard a\nrequest explicitly .\u003cbr/\u003e\nTherefore the rule quickly becomes *feel free to make a request and forget about\nit*. It's as simple as calling a member function on them.\n\n## The Loop and the Resource\n\nThe first thing to do to use `uvw` is to create a loop. In case the default one\nis enough, it's easy as doing this:\n\n```cpp\nauto loop = uvw::loop::get_default();\n```\n\nNote that loop objects don't require being closed explicitly, even if they offer\nthe `close` member function in case a user wants to do that.\u003cbr/\u003e\nLoops can be started using the `run` member function. The two calls below are\nequivalent:\n\n```cpp\nloop-\u003erun();\nloop-\u003erun(uvw::loop::run_mode::DEFAULT);\n```\n\nAvailable modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the\ndocumentation of `libuv` for further details.\n\nIn order to create a resource and to bind it to the given loop, just do the\nfollowing:\n\n```cpp\nauto tcp = loop-\u003eresource\u003cuvw::tcp_handle\u003e();\n```\n\nThe line above creates and initializes a tcp handle, then a shared pointer to\nthat resource is returned.\u003cbr/\u003e\nUsers should check if pointers have been correctly initialized: in case of\nerrors, they won't be.\u003cbr/\u003e\nIt also is possible to create uninitialized resources to init later on as:\n\n```cpp\nauto tcp = loop-\u003euninitialized_resource\u003cuvw::tcp_handle\u003e();\ntcp-\u003einit();\n```\n\nAll resources also accept arbitrary user-data that won't be touched in any\ncase.\u003cbr/\u003e\nUsers can set and get them through the `data` member function as it follows:\n\n```cpp\nresource-\u003edata(std::make_shared\u003cint\u003e(42));\nstd::shared_ptr\u003cvoid\u003e data = resource-\u003edata();\n```\n\nResources expect a `std::shared_pointer\u003cvoid\u003e` and return it, therefore any kind\nof data is welcome.\u003cbr/\u003e\nUsers can explicitly specify a type other than `void` when calling the `data`\nmember function:\n\n```cpp\nstd::shared_ptr\u003cint\u003e data = resource-\u003edata\u003cint\u003e();\n```\n\nRemember from the previous section that a handle will keep itself alive until\none invokes the `close` member function on it.\u003cbr/\u003e\nTo know what are the handles that are still alive and bound to a given loop,\nthere exists the `walk` member function. It returns handles with their types.\nTherefore, the use of `overloaded` is recommended to be able to intercept all\ntypes of interest:\n\n```cpp\nhandle.parent().walk(uvw::overloaded{\n    [](uvw::timer_handle \u0026h){ /* application code for timers here */ },\n    [](auto \u0026\u0026){ /* ignore all other types */ }\n});\n```\n\nThis function can also be used for a completely generic approach. For example,\nall the pending handles can be closed easily as it follows:\n\n```cpp\nloop-\u003ewalk([](auto \u0026\u0026h){ h.close(); });\n```\n\nNo need to keep track of them.\n\n## The event-based approach\n\n`uvw` offers an event-based approach where resources are small event emitters to\nwhich listeners are attached.\u003cbr/\u003e\nAttaching listeners to resources is the recommended way to receive notifications\nabout their operations.\u003cbr/\u003e\nListeners are callable objects of type `void(event_type \u0026, resource_type \u0026)`,\nwhere:\n\n* `event_type` is the type of the event for which they have been designed.\n* `resource_type` is the type of the resource that has originated the event.\n\nIt means that the following function types are all valid:\n\n* `void(event_type \u0026, resource_type \u0026)`\n* `void(const event_type \u0026, resource_type \u0026)`\n* `void(event_type \u0026, const resource_type \u0026)`\n* `void(const event_type \u0026, const resource_type \u0026)`\n\nPlease note that there is no need to keep around references to the resources,\nsince they pass themselves as an argument whenever an event is published.\u003cbr/\u003e\nThe `on` member function is the way to go to register long-running listeners:\n\n```cpp\nresource.on\u003cevent_type\u003e(listener)\n```\n\nTo know if a listener exists for a given type, the class offers a `has` function\ntemplate. Similarly, the `reset` function template is be used to reset and thus\ndisconnect listeners, if any. A non-template version of `reset` also exists to\nclear an emitter as a whole.\n\nAlmost all the resources emit `error_event` in case of errors.\u003cbr/\u003e\nAll the other events are specific for the given resource and documented in the\nAPI reference.\n\nThe code below shows how to create a simple tcp server using `uvw`:\n\n```cpp\nauto loop = uvw::loop::get_default();\nauto tcp = loop-\u003eresource\u003cuvw::tcp_handle\u003e();\n\ntcp-\u003eon\u003cuvw::error_event\u003e([](const uvw::error_event \u0026, uvw::tcp_handle \u0026) { /* something went wrong */ });\n\ntcp-\u003eon\u003cuvw::listen_event\u003e([](const uvw::listen_event \u0026, uvw::tcp_handle \u0026srv) {\n    std::shared_ptr\u003cuvw::tcp_handle\u003e client = srv.parent().resource\u003cuvw::tcp_handle\u003e();\n    client-\u003eon\u003cuvw::end_event\u003e([](const uvw::end_event \u0026, uvw::tcp_handle \u0026client) { client.close(); });\n    client-\u003eon\u003cuvw::data_event\u003e([](const uvw::data_event \u0026, uvw::tcp_handle \u0026) { /* data received */ });\n    srv.accept(*client);\n    client-\u003eread();\n});\n\ntcp-\u003ebind(\"127.0.0.1\", 4242);\ntcp-\u003elisten();\n```\n\nNote also that `uvw::tcp_handle` already supports _IPv6_ out-of-the-box.\u003cbr/\u003e\nThe API reference is the recommended documentation for further details about\nresources and their methods.\n\n## Going raw\n\nIn case users need to use functionalities not wrapped yet by `uvw` or if they\nwant to get the underlying data structures as defined by `libuv` for some other\nreasons, almost all the classes in `uvw` give direct access to them.\u003cbr/\u003e\nPlease, note that this functions should not be used directly unless users know\nexactly what they are doing and what are the risks. Going raw is dangerous,\nmainly because the lifetime management of a loop, a handle or a request is\ncompletely controlled by the library and working around it could quickly break\nthings.\n\nThat being said, _going raw_ is a matter of using the `raw` member functions:\n\n```cpp\nauto loop = uvw::loop::get_default();\nauto tcp = loop-\u003eresource\u003cuvw::tcp_handle\u003e();\n\nuv_loop_t *raw = loop-\u003eraw();\nuv_tcp_t *handle = tcp-\u003eraw();\n```\n\nGo the raw way at your own risk, but do not expect any support in case of bugs.\n\n\n# Related projects\n\nInterested in additional tools and libraries that build upon `uvw`? You might\nfind the following useful then:\n\n- [`uvw_net`](https://github.com/mincequi/uvw_net): a networking library with a\n  collection of clients (HTTP/Modbus/SunSpec) that also includes discovery\n  impementations like dns-sd/mdns.\n\nFeel free to add your tool to the list if you like.\n\n# Contributors\n\nIf you want to contribute, please send patches as pull requests against the\nbranch master.\u003cbr/\u003e\nCheck the\n[contributors list](https://github.com/skypjack/uvw/blob/master/AUTHORS) to see\nwho has partecipated so far.\n\n# License\n\nCode and documentation Copyright (c) 2016-2024 Michele Caini.\u003cbr/\u003e\nLogo Copyright (c) 2018-2021 Richard Caseres.\n\nCode and documentation released under\n[the MIT license](https://github.com/skypjack/uvw/blob/master/LICENSE).\u003cbr/\u003e\nLogo released under\n[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).\n\n# Support\n\nIf you want to support this project, you can\n[offer me](https://github.com/users/skypjack/sponsorship) an espresso.\u003cbr/\u003e\nIf you find that it's not enough, feel free to\n[help me](https://www.paypal.me/skypjack) the way you prefer.\n","funding_links":["https://github.com/sponsors/skypjack","https://www.paypal.me/skypjack"],"categories":["TODO scan for Android support in followings","Asynchronous Event Loop","C++","Networking Libraries","Networking","Table of Contents"],"sub_categories":["UI Test Automation Scripting"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskypjack%2Fuvw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskypjack%2Fuvw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskypjack%2Fuvw/lists"}