Compare commits

...

407 Commits

Author SHA1 Message Date
Michele Caini
cb15b5aa1b linter: disable avoid-c-arrays (not ready for that yet) 2024-12-05 17:00:08 +01:00
xndcn
93476594ee
doc: fix typo (uwv -> uvw) (#321) 2024-12-03 15:05:12 +01:00
Michele Caini
04cb432e72 linter: disable bugprone-easily-swappable-parameters (too big of an effort today) 2024-10-24 12:46:51 +02:00
Michele Caini
242838e3f3 *: cleanup 2024-10-24 09:28:13 +02:00
Michele Caini
0a993494e2 udp: avoid C-style arrays 2024-10-24 08:31:14 +02:00
Michele Caini
a3f2a6e3ac fs: avoid unnecessary array 2024-10-23 18:01:29 +02:00
Michele Caini
58b8b3d610 util: avoid C-style arrays 2024-10-23 10:38:32 +02:00
Michele Caini
998a86975b stream: avoid C-style arrays 2024-10-23 10:35:37 +02:00
Michele Caini
6bb7a6f291 work: cleanup 2024-10-23 10:33:42 +02:00
Michele Caini
32f06f4fe8 thread: cleanup 2024-10-23 10:33:36 +02:00
Michele Caini
f26fe9dea8 fs: avoid C-style arrays 2024-10-23 10:27:34 +02:00
Michele Caini
d5ea72a18a uv_type: cleanup 2024-10-23 10:22:03 +02:00
Michele Caini
8b2aa01b3d stream: [[nodiscard]] 2024-10-23 09:31:27 +02:00
Michele Caini
35c840ab61 lib: [[nodiscard]] 2024-10-23 09:30:21 +02:00
Michele Caini
08350199e3 request: [[nodiscard]] 2024-10-23 09:30:03 +02:00
Michele Caini
e774913db9 *: perf improvements 2024-10-23 09:28:51 +02:00
Michele Caini
949e46642a util: use std::array 2024-10-23 09:17:06 +02:00
Michele Caini
3a8c06fe5b test: minor changes 2024-10-23 08:56:22 +02:00
Michele Caini
e4bb43bce7 util: thanks msvc for accepting invalid code 2024-10-23 08:56:13 +02:00
Michele Caini
3c57dd9a98 test: minor changes 2024-10-23 08:51:15 +02:00
Michele Caini
3754bfe088 process:: suppress warning due to [[nodiscard]] 2024-10-23 08:51:09 +02:00
Michele Caini
cef9d850d8 util: [[nodiscard]] 2024-10-23 08:50:54 +02:00
Michele Caini
04a7c36e7b fs: explicit override 2024-10-23 08:42:35 +02:00
Michele Caini
9adfaf25ca util: move ctor params as possible 2024-10-23 08:39:19 +02:00
Michele Caini
8c10ef9de7 loop: explicit override 2024-10-23 08:37:03 +02:00
Michele Caini
78e410dc1a resource: [[nodiscard]] 2024-10-23 08:36:11 +02:00
Michele Caini
258ddaed5f uv_type: [[nodiscard]] 2024-10-23 08:35:37 +02:00
Michele Caini
70572c4424 handle: [[nodiscard]] 2024-10-23 08:33:58 +02:00
Michele Caini
5be31bad4c emitter: [[nodiscard]] 2024-10-23 08:33:52 +02:00
Michele Caini
d4f217f9f1 test: avoid deprecated headers 2024-10-23 08:30:45 +02:00
Michele Caini
6e0fe7b8c6 type_info: char to unsigned char conversion before using the value 2024-10-23 08:29:51 +02:00
Michele Caini
2b4a0f158b poll: instruct the linter on libuv callbacks 2024-10-23 08:29:27 +02:00
Michele Caini
34d2b00441 test: instruct the linter 2024-10-22 19:38:03 +02:00
Michele Caini
eb06aed649 fs_event: instruct the linter 2024-10-22 19:37:53 +02:00
Michele Caini
7cb57e0c46 fs: use make_unique if possible 2024-10-22 19:32:03 +02:00
Michele Caini
b771134121 clang-tidy: enable more checks 2024-10-22 19:24:19 +02:00
Michele Caini
dd63b4e225 type_info: internal changes 2024-10-22 19:19:17 +02:00
Michele Caini
b53cd6fd8b util: refine try_read 2024-10-22 09:25:15 +02:00
Michele Caini
a4657c479d util: passwd cannot be noexcept 2024-10-22 09:25:07 +02:00
Michele Caini
39c142fa56 enum: avoid using reserved identifiers 2024-10-22 08:00:46 +02:00
Michele Caini
a578b44788 build: updated workflow 2024-10-21 11:03:14 +02:00
Michele Caini
21372c17e8 build: split h/ipp/cpp and update clang-tidy config 2024-10-21 10:57:36 +02:00
Michele Caini
f70a0dbc2b cmake: a couple of fixes to the build system 2024-10-18 17:31:54 +02:00
Michele Caini
fb2f8d9eff cmake: use UVW_ to avoid polluting parent projects 2024-10-18 15:09:24 +02:00
Michele Caini
4d54eb946f iwyu: basic config to start with 2024-10-18 12:28:03 +02:00
Michele Caini
98dd44b5eb linter: let's start with something simple 2024-10-18 12:27:49 +02:00
Michele Caini
7261037df8 build: add missing \ 2024-10-17 18:36:45 +02:00
Michele Caini
0784a26081 build: rename file 2024-10-17 18:34:05 +02:00
Michele Caini
a89a4155ea build: fix typos 2024-10-17 18:22:51 +02:00
Michele Caini
25feca605d build: tools workflow (first draft, to be tested) 2024-10-08 16:40:59 +02:00
Michele Caini
4a1f1c6daa thread: set/get priority 2024-10-03 17:29:44 +02:00
Michele Caini
1678cdbddd utility: resident_set_memory 2024-10-03 16:08:01 +02:00
Michele Caini
a38f5452d8 build: prepare to work with libuv 1.49 2024-10-03 09:53:46 +02:00
Ruurd Adema
44541bd1bd
event: make error_event copy assignable (#316) 2024-09-05 09:36:57 +02:00
brenfwd
a4436b746e
build(meson): bump libuv to 1.48.0 (#314) 2024-05-15 17:10:40 +02:00
Michele Caini
204e31d481 now working on v3.5.0 2024-05-13 12:28:35 +02:00
Michele Caini
d32ddd2970 doc: related projects - close #313 2024-05-13 12:25:09 +02:00
Michele Caini
c64c538b6c doc: update min doxy version 2024-05-13 12:21:08 +02:00
Michele Caini
63af166c32 process: WINDOWS_FILE_PATH_EXACT_NAME 2024-05-13 12:14:38 +02:00
Michele Caini
4c9520165e build: prepare to work with libuv 1.48 2024-05-13 12:13:45 +02:00
brenfwd
ba10b27646
build: add initial meson support (#306) 2024-02-08 14:03:38 +01:00
Michele Caini
a497837cc9 now working on v3.4.0 2024-02-06 10:04:57 +01:00
Michele Caini
f3414a0603 doc: updated copyright 2024-02-06 09:48:06 +01:00
Michele Caini
ed5b527559 build: prepare to work with libuv 1.47 2024-02-06 09:47:43 +01:00
Alois Klink
b32fd63c83
ci: fail Ubuntu CI if there are compiler warnings (#304) 2023-09-06 14:41:47 +02:00
Alois Klink
683883b08a
test: fix compiler warnings in test directory (#302) 2023-09-01 09:22:50 +02:00
Alois Klink
8830320c60
uv_type: make ~uv_type() destructor protected (#303) 2023-08-30 16:18:30 +02:00
Michele Caini
77b91ff98e test: I removed a bit too much stuff with the last commit :) 2023-08-30 10:50:05 +02:00
Michele Caini
dea293ffaa uv_type: drop virtual init function - close #302 2023-08-30 09:33:39 +02:00
Alois Klink
b004e1a808
util: fix -Wsign-conversion in ip_addr() (#298) 2023-08-28 11:33:11 +02:00
Alois Klink
3eaf8efc37
pipe: hide pipe_handle::connect -Wsign-conversion (#299) 2023-08-28 11:32:32 +02:00
Alois Klink
113772521d
type_info: avoid gcc-7 -Wsign-conversion warning (#301) 2023-08-27 15:32:58 +02:00
Alois Klink
0c866baaf7
tty: remove unnecessary semi-colon (#300) 2023-08-25 17:44:16 +02:00
Alois Klink
87e5440e00
uv_type: supress -Werror=unused compiler errors (#296) 2023-08-25 17:43:02 +02:00
Alois Klink
9c88a9b352
loop: rename variable to fix -Wshadow warning (#297) 2023-08-25 17:42:01 +02:00
Reimu NotMoe
36b586f7d3
build: fix minor typo in CMakeLists.txt (#295) 2023-08-21 13:41:45 +02:00
Michele Caini
d88bfcae87 now working on v3.3.0 2023-07-03 14:51:23 +02:00
Michele Caini
7fda7c5072 pipe: use UV_PIPE_NO_TRUNCATE as needed 2023-07-03 14:40:46 +02:00
Michele Caini
14cb806b1c build: prepare to work with libuv 1.46 2023-07-03 14:29:50 +02:00
Michele Caini
042da09665 stream/udp: add support to custom allocation functions - close #289 2023-07-03 14:16:41 +02:00
Michele Caini
18081ecb66 emitter: use more meaningful names for template arguments 2023-06-09 12:11:29 +02:00
Michele Caini
2da8140e2d updated .gitignore 2023-05-22 11:15:51 +02:00
Michele Caini
def75703a4 now working on v3.2.0 2023-05-22 11:01:28 +02:00
Michele Caini
426988b000 loop: metrics 2023-05-19 14:57:15 +02:00
Michele Caini
f86c810aea util: avoid testing constrained_memory 2023-05-19 14:56:29 +02:00
Michele Caini
06f084d4ba thread: getcpu 2023-05-19 14:44:33 +02:00
Michele Caini
8743dfc155 util: available_memory + missing declarations for gettime :) 2023-05-19 14:25:21 +02:00
Michele Caini
bd90d77bc7 util: formatting 2023-05-19 14:24:08 +02:00
Michele Caini
5e4694abba util: uvw_clock_id and gettime 2023-05-19 14:23:56 +02:00
Michele Caini
f0ac08cb42 build: prepare to work with libuv 1.45 2023-05-19 14:23:08 +02:00
Michele Caini
67acfdb53b doc: fixed typo 2023-05-15 14:35:30 +02:00
Jon Daniel
cf0f8c6fd4
process: fix missing const in equality relation for C++23 (#278) 2023-05-12 08:29:43 +02:00
Benoît
ac42b79b30
process: fix ambiguous overloaded from c++20 with explicit cast (#280) 2023-05-11 14:29:57 +02:00
Michele Caini
d84a031f32 loop: add missing UVW_INLINE (close #282) 2023-05-11 14:26:20 +02:00
Reimu NotMoe
e059473135
poll: fix compile errors caused by ambiguous naming of poll_event in poll_handle (#281) 2023-05-08 08:08:30 +02:00
Michele Caini
950aa6486e fix doxygen link 2023-05-05 08:54:37 +02:00
Michele Caini
a3c179d089 now working on v3.1.0 2023-05-05 08:53:55 +02:00
Michele Caini
220c4fe13b updated doxy file 2023-05-05 08:37:44 +02:00
Michele Caini
ec1f973bd4 updated libuv version 2023-05-05 08:37:30 +02:00
Petr Menšík
6d771874a8
test: do not fail unit test because cpu speed 0 (#277) 2023-03-11 19:12:47 +01:00
Michele Caini
70697f4ae9
uvw v3 (#263) 2023-03-10 10:52:03 +01:00
Stefano Fiorentino
3636701fc2
avoid cmake complaining about using VERSION keyword (#275)
[cmake] CMake Error at CMakeLists.txt:190 (set_target_properties):
	[cmake]   INTERFACE_LIBRARY targets may only have whitelisted properties.  The
	[cmake]   property "VERSION" is not allowed.

Signed-off-by: Fiorentino, Stefano <stefano.fiorentino@adesso.ch>
Co-authored-by: Fiorentino, Stefano <stefano.fiorentino@adesso.ch>
2023-02-27 18:47:35 +01:00
Nicolas Jakob
b2ed37f5f5
doc: add vcpkg badge and vcpkg.link (#274) 2023-02-24 10:42:20 +01:00
Petr Menšík
1e4f964c47
Include cstdint where uintX_t is used (#273) 2023-02-22 18:14:31 +01:00
Michele Caini
68803053f4 doc: updated copyright 2023-01-20 08:51:29 +01:00
Stefano Fiorentino
36b9d189a1
shared object versioning (mirroring the behaviour of autotools) (#269)
* shared object versioning (mirroring the behaviour of autotools)

Closes #268

Signed-off-by: Fiorentino, Stefano <stefano.fiorentino@adesso.ch>
2023-01-16 18:15:02 +01:00
Michele Caini
897e83f66a build: updated workflows 2023-01-16 09:53:23 +01:00
Michele Caini
efcd2a3858 doc: drop download link, no longer relevant 2023-01-16 09:46:57 +01:00
Michele Caini
324ca2ac32 doc: drop links to docsforge (close #272) 2023-01-16 09:46:04 +01:00
Stefano Fiorentino
64fb9fc8e5
set workflows with only default compiler packages (#271) - close #270 2023-01-12 17:40:53 +01:00
Moody
684d912ca9
export uvwConfig to build a uvw submodule statically (#264) 2022-04-07 14:36:54 +02:00
Michele Caini
3db9e8f75a update to libuv 1.44.1 2022-03-10 11:30:41 +01:00
Michele Caini
6243d3624a added Utilities::availableParallelism (libuv 1.44) 2022-03-08 13:15:38 +01:00
Michele Caini
5664b04075 added a clang-format file, updated the whole codebase 2022-03-08 12:59:19 +01:00
Michele Caini
25b8fad800 test: remove broken check 2022-03-08 12:15:05 +01:00
Michele Caini
1d3d6dd2dc updated workflow 2022-03-08 11:54:00 +01:00
Michele Caini
2918b4e9ce updated to libuv v1.44 2022-03-08 11:37:50 +01:00
Michele Caini
9f8047d6d4 osPriorirty -> OS::priority as it ought to be 2022-03-08 11:35:56 +01:00
Petr Menšík
7326baf110
Support dynamic linkage of tests (#253) 2022-02-08 16:53:05 +01:00
Fiorentino Ing. Stefano
472245a8bd install either static or shared lib only
Close #246

Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2022-02-01 12:23:15 +01:00
Fiorentino Ing. Stefano
c8c2ccadd6 remove the configurations for pkg-config
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2022-02-01 12:23:15 +01:00
Fiorentino Ing. Stefano
62511d77bc Adding subdirectories name to the installation PATHs.
Also removing the libuv general targets from ALL

Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2022-02-01 12:23:15 +01:00
Michele Caini
2f6be7b7ab doc: release it under MIT (no need to use a different license) - close #260 2022-01-19 10:09:59 +01:00
Michele Caini
cca65db1f4 doc: updated copyright 2022-01-18 15:56:49 +01:00
Michele Caini
fa83b0fb5e type_info: remove non-UTF-8 characters (close #259) 2022-01-17 14:21:08 +01:00
Michele Caini
86fb93d0ef update to libuv v1.43 (it just works fortunately) 2022-01-14 09:17:02 +01:00
Michele Caini
432c55de9b build system: update gtest upstream branch name 2021-11-16 09:29:41 +01:00
Moody
b388750a8d
added CMake package configuration files (#246) 2021-11-11 13:52:18 +01:00
Michele Caini
5876a2b11d Add support for uv_try_write2 2021-07-28 11:29:10 +02:00
Michele Caini
a0f7be6825 Prepare for cutting v2.10 2021-07-28 11:04:58 +02:00
Fiorentino Ing. Stefano
1e6013d230 libuv version update to v1.42.0
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2021-07-28 10:59:18 +02:00
Moody
97c02c4f57
Fixed a typo in conanfile.py (#247) 2021-07-05 08:34:18 +02:00
Michele Caini
3d60ab1a6d build system: updated GH workflow 2021-06-30 14:58:44 +02:00
Michele Caini
a32596ed02 added CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS to the workflow 2021-05-10 11:36:48 +02:00
Michele Caini
67a5eab44f updated type_info.hpp 2021-05-10 11:11:56 +02:00
Michele Caini
775a7262f8 updated build system (test also older compilers) 2021-05-10 11:10:53 +02:00
Michele Caini
3ed391ab13 updated build system 2021-05-10 00:07:57 +02:00
Michele Caini
9f6bcee5be updated workflow 2021-05-09 23:50:23 +02:00
Michele Caini
d2efc89796 cleanup 2021-05-09 23:50:13 +02:00
Michele Caini
437ab75068 make internal::counter static inline 2021-05-09 23:47:11 +02:00
Michele Caini
aea6671b14 refine type hash indexing model 2021-05-09 23:42:16 +02:00
Stefano Fiorentino
010d8de944
Removing the monostate pattern from uvw. (#242) 2021-05-09 22:49:33 +02:00
Michele Caini
b0015be668 always initialize local variables (close #241) 2021-04-01 09:47:16 +02:00
Michele Caini
bf61f55dd3 loop::walk ignores unmanaged handles (close #239) 2021-03-22 15:18:39 +01:00
Michele Caini
83973cbc04 removed a bunch of unnecessary copies (close #238) 2021-03-22 12:20:21 +01:00
Michele Caini
58b299ee60 Updated to libuv 1.41 (close #237).
uv_socketpair and uv_pipe aren't explicitly eported via uwv.
2021-02-14 16:15:20 +01:00
Michele Caini
d799a7fc85 poll handle: rename variable to avoid clashing (close #236) 2021-02-11 23:26:30 +01:00
Fiorentino Ing. Stefano
2ea56b1dd1 Give the option to build uvw as lib without fetching the libuv dependency
creating a fake lib to re-activate the lib test
	closes #231

Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-11-17 13:46:31 +00:00
Michele Caini
6ed211328e make AddrFuncType in IpTraits an inline static variable rather than a constexpr one (close #226) 2020-10-15 09:39:35 +02:00
Michele Caini
e0e0be194e build system: updated cmake file for docs target 2020-10-15 09:34:54 +02:00
Stefano Fiorentino
0156258c9b
Merge pull request #224 from stefanofiorentino/experimental
refactor the `test' includes
2020-10-08 10:46:11 +02:00
Fiorentino Ing. Stefano
184488be25 refactor the `test' includes
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-10-08 08:10:11 +00:00
Stefano Fiorentino
60bd3aea38
Merge pull request #222 from stefanofiorentino/experimental
Avoid instantiations as header-only config is used.
2020-10-05 14:16:11 +02:00
Fiorentino Ing. Stefano
41257c60f2 Avoid instantiations as header-only config is used.
Closes #221

Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-10-05 08:26:43 +00:00
Michele Caini
26973f335c updated build system 2020-10-04 22:13:10 +02:00
Michele Caini
6dd4a420f8 updated to libuv 1.40 (close #220) 2020-10-03 23:02:29 +02:00
Michele Caini
77af4a3fc4 updated workflow 2020-09-10 15:42:41 +02:00
Michele Caini
6e5890921a build system: solved an issue with codecov 2020-09-07 08:46:41 +02:00
Michele Caini
13cbd81881 ready to cut a new release (close #219) 2020-09-07 08:44:41 +02:00
Michele Caini
0c1a21e75c doc: added a note about Emitter::clear (close #217) 2020-08-10 00:06:45 +02:00
Michele Caini
0e86ec5847 doc: updated documentation for Loop::walk (close #214) 2020-08-09 23:58:53 +02:00
Michele Caini
91ab230d81 a more vs-friendly gitignore file 2020-07-31 17:51:21 +02:00
Michele Caini
112828c677 test: make work.cpp run correcty also on Windows 2020-07-31 17:06:52 +02:00
Michele Caini
6b1651be7e fixed typo 2020-07-31 16:34:38 +02:00
Michele Caini
a4a27cacff test: make pipe tests run correctly also on Windows 2020-07-31 16:09:29 +02:00
Michele Caini
d2cc600e97 test: make thread tests run fine also on Windows 2020-07-31 13:01:13 +02:00
Michele Caini
9ed3eaebd1 test: make tty test run without errors also on Windows 2020-07-31 12:44:08 +02:00
Michele Caini
a77051e73a test: make util test compile also on Windows 2020-07-31 12:27:43 +02:00
Michele Caini
934851e3f5 test: make loop test compile also on Windows 2020-07-31 12:12:18 +02:00
gallexme
c3e189c612
thread.cpp: suppress narrowing conversions warnings (#216) 2020-07-31 11:20:34 +02:00
Michele Caini
0b329720bf get rid of base handle, loop::walk returns actual handles (see #212, close #214) 2020-07-28 22:34:09 +02:00
Stefano Fiorentino
a10844d4bf
basehandle::type() in uv_walk which is in a timer callback causes double free (#213)
Close #212
2020-07-19 12:08:36 +02:00
Michele Caini
52785475b9 udp: get around an issue with ICC (close #209) 2020-07-02 15:47:57 +02:00
Eli Lindsey
1a794772b2
add openbsd support (#204)
* add openbsd support

Renames fileno() so it doesn't clash with OpenBSD's macro expansion.
Makes minor changes to build steps so the test suite compiles and runs
on OpenBSD.

See https://github.com/skypjack/uvw/issues/201 for full context

* drop no-error override

* disable sendfile tests on openbsd

* forgot to commit the new file
2020-06-29 16:37:31 +02:00
Michele Caini
dc67c97ab2 doc: small review + added links to docsforge (close #210) 2020-06-29 16:29:45 +02:00
Michele Caini
f9056e732c resolve an issue with ICC (close #208) 2020-06-29 15:45:55 +02:00
Fiorentino Ing. Stefano
60614d32b8 remove all reference to shared library
too much effort to support cross-platform DSO

Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-06-29 11:10:47 +02:00
Michele Caini
00d5c11e65 doc: make it compile again and suppress some warnings 2020-05-31 16:46:47 +02:00
Michele Caini
37aa1c8260 udp: data event returns non-const data (close #200) 2020-05-27 12:31:53 +02:00
Michele Caini
3a29890651 ready to cut a new release (close #199) 2020-05-25 23:41:44 +02:00
Michele Caini
fb270887b4 updated to libuv v1.38 2020-05-25 23:38:52 +02:00
Michele Caini
e5870c79e1 doc: updated cmake minimum required version (see #194) 2020-05-21 22:35:06 +02:00
Michele Caini
fd52f76e4d doc: removed references to patreon account 2020-05-21 08:46:11 +02:00
Michele Caini
3a02460be1 build system: updated required version for cmake (close #194) 2020-05-17 22:12:33 +02:00
Eli Lindsey
d35f557161
add elindsey to contributors list (#193) 2020-04-27 16:01:43 +02:00
Michele Caini
99e6ba7124 ready to cut a new release (close #191) 2020-04-24 00:59:15 +02:00
Michele Caini
ff97bbbc9d now works with libuv v1.37 (see #191) 2020-04-24 00:57:09 +02:00
Fiorentino Ing. Stefano
3d9e45e733 Switch pragma once to legacy include guards
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-04-20 18:24:11 +02:00
Fiorentino Ing. Stefano
991f5cdbb8 Extern template instantiations to get rid of clang warnings.
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-04-19 21:27:43 +02:00
Fiorentino Ing. Stefano
938b8af9b0 Skip including header in .cpp in case UVW_AS_LIB is defined
Signed-off-by: Fiorentino Ing. Stefano <stefano.fiore84@gmail.com>
2020-04-19 18:47:32 +02:00
Michele Caini
c0b9dc919b updated to libuv v1.36 (close #191) 2020-04-18 16:45:21 +02:00
Stefano Fiorentino
4a6289ecf7 improve udp instantiations
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-06 17:37:05 +02:00
Stefano Fiorentino
ff0d29309a improve dns instantiations
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-06 16:54:07 +02:00
Stefano Fiorentino
b2647468e2 avoid to install .cpp with BUILD_UVW_LIBS
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-06 16:15:36 +02:00
Stefano Fiorentino
8872af2d86 improve tcp instantiations
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-06 16:03:45 +02:00
Stefano Fiorentino
d611ca264f Instantiate Loop::run<Mode>() in the .cpp
This is possible because a limited values are available as Mode

Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-06 15:02:26 +02:00
Stefano Fiorentino
0ee7ef41fe adding option to activate UB sanitizer
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-03 22:42:45 +02:00
Stefano Fiorentino
03b98bc234 update project description to add shared/static library
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-04-03 22:42:45 +02:00
Eli Lindsey
fc197b5117 fix undefined behavior in resource.hpp
Today, uvw triggers undefined behavior in resource.hpp:
  runtime error: downcast of address which does not point to an object of type 'uvw::FsEventHandle'
  note: object is of type 'uvw::BaseHandle'

It looks like we're saving the current handle in the void* data member
so it can be retrieved on the next callback run. This downcast to a
derived class from its parents ctor as it's being constructed isn't
valid.

Since we're storing this as a void* anyways and all the callsites using
it need to do their own cast on retrieval, we can instead persist the
this pointer. For downcasting to work in all cases the Resource class
tree needs to be leftmost in Handler's multiple inheritance.

Tested by verifying that my unit tests no longer show ubsan errors and
uvw's test suite still passes.
2020-04-02 14:37:45 -04:00
Michele Caini
8233a6e6b2 updated README file (thanks to @escherstair for pointing out some errors in the documentation) 2020-04-01 15:12:30 +02:00
Michele Caini
fda5b57f4f doc: updated README (close #187) 2020-03-31 22:54:44 +02:00
Michele Caini
1f2b6ed23d increase code coverage 2020-03-28 00:03:54 +01:00
Michele Caini
4d92e354be increase code coverage 2020-03-27 23:39:08 +01:00
Michele Caini
fc50c60987 removed dead branch (BUILD_TESTING is used already to enter the test directory) 2020-03-27 23:32:48 +01:00
Stefano Fiorentino
d9ab73a281 `make install' requires gtest and tests to be built #186
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-03-27 21:50:28 +01:00
Stefano Fiorentino
336e5dfb1d Improving test coverage [adding Mutex::RecursiveLockUnlock]
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-03-27 12:31:33 +01:00
Stefano Fiorentino
bfc4a2c95b Improving test coverage [adding Mutex::LockUnlock]
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-03-27 12:02:05 +01:00
Stefano Fiorentino
53da326aea FsReq.ReadDir test now reads all dirent's entries
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-03-25 23:14:48 +01:00
Stefano Fiorentino
6fd64f93a0 Improving test coverage [adding FsReq::readdirSync]
Signed-off-by: Stefano Fiorentino <stefano.fiore84@gmail.com>
2020-03-25 19:34:05 +01:00
Stefano Fiorentino
216f5f4da1 Improving test coverage [adding FsReq::readdir] 2020-03-25 16:04:23 +01:00
Stefano Fiorentino
fe73fa048a explicit instantiation of compile-time flag-based functionalities #183 2020-03-25 15:56:35 +01:00
Stefano Fiorentino
1f7d4acc40 Improving test coverage [adding Thread] (#181) 2020-03-25 15:55:16 +01:00
Michele Caini
008361d83c updated README.md (close #185) 2020-03-25 15:51:26 +01:00
Michele Caini
0fe8d7959b updated README.md to reflect the new dual-mode 2020-03-22 22:54:22 +01:00
Michele Caini
8d1a431f68 allow custom deleters with write requests (close #182) 2020-03-22 22:29:15 +01:00
Michele Caini
4afb5ebb20 updated list of collaborators 2020-03-21 15:54:23 +01:00
Stefano Fiorentino
0e36f685e8 Export cmake targets (close #179) 2020-03-21 15:47:50 +01:00
Stefano Fiorentino
ebc8199d42 Add support for pkg-config (close #177) 2020-03-18 23:05:06 +01:00
Michele Caini
3a32097dc8 ready to cut a new release 2020-03-16 23:25:09 +01:00
Michele Caini
855d851f47 updated to libuv v1.35 (close #175) 2020-03-16 23:23:05 +01:00
Michele Caini
55d7782af5 allow static build - see #171, thanks to @stefanofiorentino 2020-03-16 23:01:53 +01:00
Sergiu Giurgiu
76f247847f
Changed FsReq::stasfs method name to statfs (#173) 2020-03-01 21:47:43 +01:00
Michele Caini
da3b5f00f5 updated copyright 2020-01-17 23:17:07 +01:00
Michele Caini
bc88511a29 updated version 2020-01-17 23:14:58 +01:00
Michele Caini
1b6d9625e8 updated libuv reference 2020-01-17 23:14:49 +01:00
Michele Caini
ba618cf070 stream: fixed extended write functions (close #169) 2020-01-16 19:37:39 +01:00
Michele Caini
3e6b09eb8d build system: fixed cmake option to generate documentation 2019-12-05 14:12:37 +01:00
Michele Caini
ed766f709a now working with libuv v1.34.x 2019-12-04 23:05:47 +01:00
Michele Caini
8f868995fc updated workflow 2019-11-08 09:56:22 +01:00
Fabrice Fontaine
2cef4d6f20 CMakeLists.txt: add BUILD_DOC option (#165)
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2019-11-07 23:13:11 +01:00
Adam Leskis
7a8e526adf update typos and ambiguous phrases in README (#163)
* update typos and ambiguous phrases in README
* add name to authors list
2019-10-23 23:47:44 +02:00
Michele Caini
337bd035a8 now working with libuv v1.33.x 2019-10-17 23:42:48 +02:00
Michele Caini
3fae068b9b added Utilities::OS::env overload to iterate all env variables 2019-10-17 22:47:57 +02:00
Michele Caini
0890c29b7e updated version/libuv 2019-10-17 22:46:46 +02:00
Michele Caini
852b9e2489 GH sponsorship 2019-10-08 22:54:19 +02:00
Michele Caini
6dfe8f839a added become-patron badge 2019-09-25 15:18:36 +02:00
Michele Caini
2cb056ec7b removed appveyor.yml 2019-09-25 15:11:22 +02:00
Michele Caini
b117c6118b conan deploy through GH actions 2019-09-25 14:58:16 +02:00
Michele Caini
90affa4d51 removed appveyor.yml 2019-09-25 14:52:52 +02:00
Michele Caini
866beeda31 updated build.yml 2019-09-25 14:22:19 +02:00
Michele Caini
8a8610a928 make dns test optional 2019-09-25 14:15:15 +02:00
Michele Caini
87e23c74b5 GH actions 2019-09-25 14:04:54 +02:00
Michele Caini
6f6294ebc2 now working with libuv v1.32.x 2019-09-10 15:54:59 +02:00
Michele Caini
3264417f15 added Loop::create overload to allow using external resources (close #157) 2019-08-28 16:40:24 +02:00
Michele Caini
ea4b6c84d0 now working with libuv v1.31.x 2019-08-10 22:55:15 +02:00
Michele Caini
749581309e uvw is now a C++17 only library (close #155) 2019-07-31 14:56:51 +02:00
Michele Caini
6ce60d4088 now working with libuv v1.30.x (close #153) 2019-06-28 14:47:06 +02:00
Michele Caini
6852f49401
Update FUNDING.yml 2019-06-07 09:54:38 +02:00
Michele Caini
af80bf5ef1
Create FUNDING.yml 2019-06-06 11:55:01 +02:00
Michele Caini
e59a989521 Revert "minor changes"
This reverts commit 8a93cb6e31.
2019-05-27 15:00:13 +02:00
Michele Caini
ff19fe0bc1 updated version 2019-05-27 14:52:25 +02:00
Michele Caini
0186f0444c reset the loop on close (fix #152) 2019-05-27 14:46:36 +02:00
Michele Caini
8a93cb6e31 minor changes 2019-05-27 14:45:33 +02:00
Michele Caini
529ebf3b49 updated doc 2019-05-20 23:03:00 +02:00
Michele Caini
aa43978b3e updated list of authors 2019-05-20 14:12:30 +02:00
Michele Caini
34042167eb updated README.md (as suggested by RevRagnarok from Reddit) 2019-05-17 08:37:45 +02:00
Michele Caini
1dc61d523d now working with libuv v1.29.x (close #151) 2019-05-16 14:22:40 +02:00
Michele Caini
b127f58e41 avoid narrowing conversions 2019-04-25 09:18:40 +02:00
Michele Caini
00c19381fc now working with libuv v1.28.x (close #149) 2019-04-25 00:05:36 +02:00
Michele Caini
6f5c43ae8e now working with libuv v1.27.x (close #148) 2019-03-20 17:31:51 +01:00
Michele Caini
8349a74801 bug fixing 2019-03-17 17:23:57 +01:00
Michele Caini
995603f6fe updated version 2019-03-09 23:46:02 +01:00
Michele Caini
6b64e20161 doc: thread.hpp 2019-03-09 23:44:02 +01:00
Michele Caini
c053e861e8 updated list of patrons 2019-03-08 15:28:57 +01:00
Michele Caini
e9685cfbe7 updated README 2019-03-01 08:40:35 +01:00
Michele Caini
78df87fddd minor changes (close #147) 2019-02-27 17:07:11 +01:00
Michele Caini
b269d9cfa6 now working with libuv v1.26.x (close #146) 2019-02-14 22:40:21 +01:00
Uilian Ries
7c043fae5e #144 Remove Conan remotes (#145)
- Since liuv is official in Conan Center, we no loger need to force
  Bincrafters' remote in CPT list.
- Add topics attribute. All topics are present on Github project page.

Signed-off-by: Uilian Ries <uilianries@gmail.com>
2019-01-29 22:29:28 +01:00
Michele Caini
8fbb39fd52 updated conan stuff 2019-01-24 14:27:26 +01:00
Michele Caini
27dc68dd84 now working with libuv v1.25.x 2019-01-24 14:03:33 +01:00
Michele Caini
af3d06f3b4 updated copyright 2019-01-02 15:34:08 +01:00
Michele Caini
183ebc0333 fix #142 2018-11-20 14:38:49 +01:00
Michele Caini
41913613c0 updated conanfile.py 2018-11-17 15:09:51 +01:00
Michele Caini
2167cddb01 now working with libuv v1.24.x 2018-11-17 15:02:31 +01:00
Michele Caini
ae8f5c81d4 skip tests from libuv 2018-11-06 15:07:31 +01:00
Michele Caini
c11d30ddba fixed appveyor configuration 2018-11-06 14:53:55 +01:00
Michele Caini
c0edac3cf3 fixed conan cpp 2018-11-06 14:49:10 +01:00
Michele Caini
a9bad602df renaming 2018-11-06 14:34:49 +01:00
Michele Caini
88d718d490 fixed conan badge 2018-10-25 21:52:07 +02:00
Michele Caini
a516cd8b55 updated .gitignore 2018-10-25 17:13:09 +02:00
Michele Caini
a17ec9037a conan package support 2018-10-25 17:10:39 +02:00
Michele Caini
f42d15005b fixed link to license 2018-10-24 14:57:22 +02:00
Michele Caini
9eaab52bd2 v1.11.2 RC 2018-10-12 00:07:23 +02:00
Jasper Wan
629edd3a61 fix compilation error in stream.hpp on vs2017 (#134) 2018-10-09 21:39:52 +02:00
Michele Caini
8d8338a135 updated contributors list 2018-10-08 22:47:14 +02:00
Michele Caini
bd4de26f70
Update README.md 2018-10-08 22:42:08 +02:00
Qix
acfa05a326 Follow ctest and BUILD_TESTING best practices (#131) 2018-10-06 14:30:07 +02:00
zxtwonder
c4864f1a5b Remove always-added stdin in uvw::ProcessHandle (#129) 2018-10-04 15:58:07 +02:00
Michele Caini
3523ec5439 fixed copyright note 2018-10-02 10:45:08 +02:00
Michele Caini
e89da65240 added link to patreon 2018-09-29 22:43:35 +02:00
Michele Caini
b580b20e18 added logo 2018-09-26 13:49:10 +02:00
Michele Caini
6a862c0c44
Update README.md 2018-09-13 15:01:27 +02:00
Michele Caini
857d652ddf now working with libuv v1.23.x 2018-08-22 23:37:37 +02:00
Tushar Maheshwari
bd520c40ba set C compiler for coverage (#125) 2018-08-22 22:49:57 +02:00
Tushar Maheshwari
90ac2149f9 CMake updates (#123)
* single dependency file
* Disable testing for dependencies
* Move enable_testing before dependencies
2018-08-19 14:07:02 +02:00
Michele Caini
2722f559cb updated version 2018-08-01 18:07:58 +02:00
Pavel
482837faec A fix to process I/O initialization. Closes #119. (#120) 2018-08-01 18:06:43 +02:00
Michele Caini
1e41480587 now working with libuv v1.22.x 2018-07-10 16:57:43 +02:00
Jan Olszak
962923c9cd Fix cross-compilation (#116) 2018-07-09 10:44:48 +02:00
Michele Caini
d35bd0aa92 updated version 2018-06-27 13:50:31 +02:00
Michele Caini
764f78ad61 now working with libuv v1.21.x 2018-06-27 13:40:48 +02:00
Michele Caini
10ae3f4e2e #115 (thank to @janekolszak) + minor changes 2018-06-25 09:19:38 +02:00
Michele Caini
99946ba004 fixed #114 2018-04-12 12:10:10 +02:00
Michele Caini
f6de644eea now working with libuv v1.20.0 2018-04-03 13:35:58 +02:00
Thomas Versteeg
55db2ba084 Add missing code to wrong example in README.md (#112) 2018-02-27 22:08:07 +01:00
bmagistro
7abf541dc5 FEATURE: expose write_queue_size (#109)
more functions exposed by stream and udp
2018-02-05 22:35:34 +01:00
Michele Caini
f3da3a8476 updated copyright 2018-01-26 17:26:19 +01:00
Michele Caini
94f2060c37 trying to reproduce #108 2018-01-22 22:31:56 +01:00
Michele Caini
12084dc85a updated doc 2018-01-19 11:41:36 +01:00
Michele Caini
a9e8fc17b5 updated loop 2018-01-19 11:19:00 +01:00
Michele Caini
ec837c9d6e updated to libuv v1.19.0 2018-01-19 11:18:48 +01:00
Michele Caini
46d9c66db1 now working with libuv v1.18.0 2017-12-03 15:32:27 +01:00
Michele Caini
7f9fdf7f73 now working with libuv v1.17.0 2017-11-29 14:04:35 +01:00
Michele Caini
76ab069eda #105 2017-11-29 12:30:13 +01:00
Michele Caini
1e2c566295 improved low-level interface for tcp/udp/dns 2017-11-28 14:13:16 +01:00
Michele Caini
38414e3063 #102: improved low-level TCP connection interface 2017-11-27 16:39:19 +01:00
Michele Caini
badda7e702 cleanup 2017-11-20 14:10:40 +01:00
Michele Caini
dba9a2043b clean up 2017-11-07 08:22:31 +01:00
Michele Caini
e26c728d69 now working with libuv v1.16.0 2017-11-06 23:49:48 +01:00
Michele Caini
ba22ea0a36 minor changes 2017-10-27 14:06:47 +02:00
Michele Caini
9b77cc47e8 fixed typo 2017-10-18 15:47:41 +02:00
Michele Caini
c99ada340c Update README.md 2017-10-16 23:22:35 +02:00
Michele Caini
f36a18f54d updated README 2017-10-13 14:32:28 +02:00
Michele Caini
b2d1c9bd7a Update README.md 2017-10-11 09:21:27 +02:00
Michele Caini
c98a54a0cf minor changes 2017-10-11 08:57:12 +02:00
Michele Caini
efd66f07dd now working with libuv v1.15.0 2017-10-05 13:55:22 +02:00
Michele Caini
356c57b8e5 minor changes 2017-09-25 08:54:06 +02:00
Michele Caini
3b28f21a32 Update CMakeLists.txt 2017-09-14 08:30:20 +02:00
Michele Caini
90aa53f68d WIP: tests 2017-09-13 22:43:31 +02:00
Michele Caini
281a8eb96a cleanup 2017-09-13 22:28:02 +02:00
Michele Caini
fe850bb83c small refactoring 2017-09-12 13:50:45 +02:00
Michele Caini
253d3302d2 update AUTHORS 2017-09-12 13:41:32 +02:00
bmagistro
ba9b8b459f return eagain if nread is 0 per libuv (#100)
Suppress EAGAIN/EWOULDBLOCK equivalents.
2017-09-12 13:39:58 +02:00
Michele Caini
9b4c6373b0 Update README.md 2017-09-09 15:28:12 +02:00
Michele Caini
f1dfeea41b WIP: tests 2017-09-08 23:36:40 +02:00
Michele Caini
a1fad242f7 updated AUTHORS 2017-09-08 22:26:54 +02:00
Michele Caini
3980f38842 updated libuv.in 2017-09-08 10:15:53 +02:00
Michele Caini
b26586f870 WIP: tests 2017-09-08 10:13:13 +02:00
Michele Caini
20a554b93e WIP: tests 2017-09-08 09:48:13 +02:00
Michele Caini
1378ba152f docs 2017-09-08 09:25:01 +02:00
Michele Caini
dd841bb813 BaseHandle::type/BaseHandle::category functionalities 2017-09-08 09:10:01 +02:00
Michele Caini
cf14a05eb0 removed useless + 2017-09-06 22:37:51 +02:00
Michele Caini
ce681db619 WIP: tests 2017-09-06 22:26:08 +02:00
Michele Caini
3e1cdf7965 WIP: tests 2017-09-02 22:10:08 +02:00
Michele Caini
a8cdb4a6a1 updated contributors list 2017-08-28 23:37:51 +02:00
Slyshyk Oleksiy
61d126020d Fix compilation on win32 (#97)
* fix build flags for WIN32
* make mingw happy with template params
* correct few remarks
* declare StreamHandle constructor only for MSVC
* Return to old declaration of StreamHandle constructor
2017-08-28 23:34:17 +02:00
Michele Caini
01488c71df WIP: tests 2017-08-28 23:32:57 +02:00
Michele Caini
f76f911c98 fixed: ProcessHandle::cwd declaration 2017-08-28 23:29:25 +02:00
Michele Caini
6b869f980d WIP: tests 2017-08-28 23:20:25 +02:00
Michele Caini
72f063ddf1 cleanup (QTCREATOR_FALLBACK is no longer required) 2017-08-28 15:08:52 +02:00
Michele Caini
a05733db59 now working with libuv 1.14.0 2017-08-18 19:09:41 +02:00
Michele Caini
383182e4b0 WIP: review process 2017-08-18 17:44:14 +02:00
Michele Caini
97e0830794 fixed (everything is now back in place after #94) 2017-08-18 17:43:54 +02:00
Michele Caini
502870ed90 fixed docs 2017-08-18 17:16:03 +02:00
Michele Caini
bbb84b0855 more tests 2017-08-06 15:15:49 +02:00
Michele Caini
806509795e more tests 2017-08-05 23:31:36 +02:00
Michele Caini
d9b070500f docs 2017-08-05 22:58:53 +02:00
Michele Caini
debddbf92a updated requirements 2017-08-05 22:35:04 +02:00
Michele Caini
4ae98c0278 cleanup 2017-08-01 17:39:24 +02:00
Michele Caini
cef596e908 minor changes 2017-08-01 17:35:59 +02:00
Tushar Maheshwari
795c6a8032 Common create method (#94)
* introduce resource_base
* Fix name resolving for ConstructorAccess
* Remove cross-ResourceBase friendship
* Rename to `UnderlyingType`
2017-08-01 17:21:35 +02:00
Michele Caini
13976fa3c5 Update AUTHORS 2017-07-25 22:41:00 +02:00
Miigon
d25e19992e tests: fix incorrect len of data in Udp ReadSend (#95) 2017-07-25 22:40:18 +02:00
Michele Caini
ba0a5a19d6 fixed (there was an UB out there) 2017-07-25 14:20:02 +02:00
Michele Caini
321be70811 fixed 2017-07-24 14:03:03 +02:00
Tushar Maheshwari
0c923be03d CMake and Travis config updates (#93)
* clean cmake usage
* reduce duplication
* deduplication
* Go travis
* Address review comments
2017-07-24 13:43:27 +02:00
Michele Caini
8ccdd51eb6 more tests 2017-07-23 11:46:41 +02:00
Michele Caini
1ed4c90225 Update AUTHORS 2017-07-23 10:52:20 +02:00
Wojciech Bartnik
0622f4f1ac Enabled syntax hightlight in example in readme (#92)
Syntax highlighting makes reading source code easier
2017-07-23 10:51:45 +02:00
Michele Caini
f4b59fb3e8 Update README.md 2017-07-17 14:05:10 +02:00
Michele Caini
6fdbec7852 Update README.md 2017-07-17 11:18:42 +02:00
Michele Caini
933738a631 tests: review (#91)
tests: review
2017-07-12 22:55:58 +02:00
Michele Caini
b294b4fbd5 Test FsPollHandle (#90)
Test FsPollHandle
2017-07-11 21:14:21 +02:00
Michele Caini
799965298a Test fs event (#89)
tests for fs_event
2017-07-10 22:59:05 +02:00
Michele Caini
7da264b3f3 tests, fs_event: rollback, still incomplete 2017-07-09 16:19:29 +02:00
Michele Caini
34119bfcd2 tests 2017-07-09 15:42:21 +02:00
Michele Caini
60f5d7124d tests + minor changes 2017-07-09 15:04:44 +02:00
Michele Caini
26ecda371c tests 2017-07-09 14:17:00 +02:00
Michele Caini
389f0baad0 fixed tests 2017-07-09 00:32:37 +02:00
Michele Caini
e27c4d3f7d workaround: see https://github.com/libuv/libuv/issues/1406 2017-07-07 13:25:02 +02:00
Michele Caini
5e456163f1 invoke functions can have void return type 2017-07-07 13:24:32 +02:00
Michele Caini
e8d38bcd6e now working on v1.1.1_libuv-v1.13 2017-07-07 09:38:51 +02:00
Michele Caini
00de1f1110 it just works as-is with libuv 1.13.* 2017-07-07 09:36:19 +02:00
Michele Caini
c37019801c now working on v1.1.0_libuv-v1.13 2017-07-06 10:01:11 +02:00
Michele Caini
1c2e1b3e90 updated version 2017-07-06 09:23:45 +02:00
Michele Caini
f922d84d9d Update AUTHORS 2017-07-06 09:18:38 +02:00
Daniel Filonik
e14d44d12e Fixed Watch/Event flags. (#88)
* Fixed Watch/Event flags.
* Changed parameter name to flag.
* Changed parameter name to "flag".
* Replaced "Watch" with "details::UVFsEvent".
2017-07-06 09:17:45 +02:00
Michele Caini
9b0185a4a4 Merge branch 'master' of https://github.com/skypjack/uvw 2017-07-06 09:16:37 +02:00
Michele Caini
48f6525711 Update README.md 2017-07-04 09:21:14 +02:00
Michele Caini
88a7d08db8 updated .gitignore 2017-06-18 16:19:07 +02:00
Michele Caini
f877cf340c WIP: tests 2017-06-18 15:37:41 +02:00
Michele Caini
5a10ca65a1 WIP: tests 2017-06-17 22:41:32 +02:00
Michele Caini
c3537ce52f Revert "me trying to solve the timing issue with WorkReq (damnit)"
This reverts commit ab118fb712.
2017-06-16 15:46:16 +02:00
Michele Caini
23a60af1e7 tests: lib 2017-06-16 15:35:02 +02:00
Michele Caini
9adfeb3060 WIP: tests/coveralls 2017-06-16 12:54:36 +02:00
Michele Caini
ab118fb712 me trying to solve the timing issue with WorkReq (damnit) 2017-06-16 11:28:07 +02:00
Michele Caini
af93044ded tests 2017-06-16 11:00:49 +02:00
Michele Caini
40ca3fd469 tests + fixed uvw::Loop::configure 2017-06-16 10:47:46 +02:00
Michele Caini
34adf15a24 tests 2017-06-15 18:11:02 +02:00
Michele Caini
c3c48c34f7 Revert "fixed tests: work"
This reverts commit 68af870e50.
2017-06-15 17:51:11 +02:00
Michele Caini
68af870e50 fixed tests: work 2017-06-15 17:39:58 +02:00
Michele Caini
9747599e3e coveralls badge 2017-06-15 17:20:40 +02:00
Michele Caini
607e6aff84 WIP: coveralls.io 2017-06-15 16:56:32 +02:00
Michele Caini
3d7a1018da updated cmake version 2017-06-15 16:56:22 +02:00
Michele Caini
acc968a8a3 WIP: coveralls.io 2017-06-15 15:42:57 +02:00
Michele Caini
5f7a913974 better doc 2017-06-14 08:49:47 +02:00
Michele Caini
36d05df0f5 review: Passwd (bug fixing + docs) 2017-06-13 14:09:00 +02:00
167 changed files with 12456 additions and 8786 deletions

41
.clang-format Normal file
View File

@ -0,0 +1,41 @@
BasedOnStyle: llvm
---
AccessModifierOffset: -4
AlignEscapedNewlines: DontAlign
AllowShortBlocksOnASingleLine: Empty
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
ColumnLimit: 0
DerivePointerAlignment: false
IncludeCategories:
- Regex: '<[[:alnum:]_]+>'
Priority: 1
- Regex: '<(gtest|gmock)/'
Priority: 2
- Regex: '<[[:alnum:]_./]+>'
Priority: 3
- Regex: '<entt/'
Priority: 4
- Regex: '.*'
Priority: 5
IndentPPDirectives: AfterHash
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
PointerAlignment: Right
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: After
SpaceBeforeCaseColon: false
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: false
Standard: Latest
TabWidth: 4
UseTab: Never

12
.clang-tidy Normal file
View File

@ -0,0 +1,12 @@
Checks: >
bugprone-*,
-bugprone-easily-swappable-parameters,
concurrency-*,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-use-trailing-return-type,
performance-*,
portability-*,
CheckOptions:
- key: bugprone-suspicious-include.HeaderFileExtensions
value: ";h;hpp;ipp"

53
.conan/build.py Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
import platform
from cpt.packager import ConanMultiPackager
def get_version():
with open("CMakeLists.txt") as cmake:
content = cmake.read()
match = re.search(r'project\(uvw VERSION (.*)\)', content)
if match:
return match.group(1)
tag_version = os.getenv("GITHUB_REF")
package_version = tag_version.replace("refs/tags/v", "")
return package_version
def get_username():
return os.getenv("CONAN_USERNAME", "skypjack")
def get_reference():
version = get_version()
username = get_username()
return "uvw/{}@{}/stable".format(version, username)
def get_upload():
username = get_username()
url = "https://api.bintray.com/conan/{}/conan".format(username)
default_upload = url if os.getenv("GITHUB_REF") else False
return os.getenv("CONAN_UPLOAD", default_upload)
def upload_when_stable():
return os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", "1").lower() not in ["0", "false", "no"]
if __name__ == "__main__":
test_folder = os.path.join(".conan", "test_package")
builder = ConanMultiPackager(reference=get_reference(),
username=get_username(),
upload=get_upload(),
test_folder=test_folder,
stable_branch_pattern=r'v?\d+\.\d+\.\d+.*',
upload_only_when_stable=upload_when_stable())
if platform.system() == "Linux":
builder.add(settings={"compiler": "gcc", "compiler.version": "8",
"arch": "x86_64", "build_type": "Release"},
options={}, env_vars={}, build_requires={})
builder.run()

View File

@ -0,0 +1,10 @@
project(test_package)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} CONAN_PKG::uvw)

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from conans import ConanFile, CMake
class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
test_package = os.path.join("bin", "test_package")
self.run(test_package, run_environment=True)

View File

@ -0,0 +1,48 @@
#include <cstdlib>
#include <iostream>
#include <uvw.hpp>
#include <memory>
void listen(uvw::loop &loop) {
std::shared_ptr<uvw::tcp_handle> tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::shared_ptr<uvw::tcp_handle> client = srv.loop().resource<uvw::tcp_handle>();
client->on<uvw::close_event>([ptr = srv.shared_from_this()](const uvw::close_event &, uvw::tcp_handle &) { ptr->close(); });
client->on<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
srv.accept(*client);
client->read();
});
tcp->bind("127.0.0.1", 4242);
tcp->listen();
}
void conn(uvw::loop &loop) {
auto tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { /* handle errors */ });
tcp->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &tcp) {
auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
tcp.write(std::move(dataWrite), 2);
tcp.close();
});
tcp->connect(std::string{"127.0.0.1"}, 4242);
}
int main() {
std::cout << "Getting UVW loop ...\n";
auto loop = uvw::loop::get_default();
std::cout << "Staring UVW listener ...\n";
listen(*loop);
std::cout << "Connecting ...\n";
conn(*loop);
loop->run();
std::cout << "Done!\n";
return EXIT_SUCCESS;
}

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: skypjack
patreon:
open_collective:
ko_fi:
tidelift:
community_bridge:
liberapay:
issuehunt:
otechie:
custom: https://www.paypal.me/skypjack

21
.github/workflows/build-macos.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: build-macos
on: [push, pull_request]
jobs:
macos:
timeout-minutes: 60
runs-on: macOS-latest
strategy:
matrix:
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
run: |
cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j2

25
.github/workflows/build-meson.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: build-meson
on: [push, pull_request]
jobs:
meson:
timeout-minutes: 60
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install Meson
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update --fix-missing
sudo apt-get install -y meson
- name: Meson Build (shared)
run: |
meson setup build
meson compile -C build
- name: Meson Build (static)
run: |
rm -rf build/
meson setup build --default-library=static
meson compile -C build

View File

@ -0,0 +1,39 @@
name: build-ubuntu-20.04
on: [push, pull_request]
jobs:
linux:
timeout-minutes: 60
strategy:
matrix:
compiler:
- { pkg: g++, exe: 'g++', version: 7 }
- { pkg: g++, exe: 'g++', version: 8 }
- { pkg: g++, exe: 'g++', version: 9 }
- { pkg: clang, exe: 'clang++', version: 8 }
- { pkg: clang, exe: 'clang++', version: 9 }
- { pkg: clang, exe: 'clang++', version: 10 }
- { pkg: clang, exe: 'clang++', version: 11 }
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }}
run: |
sudo apt-get update --fix-missing
sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }}
- name: Compile tests
env:
CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }}
run: |
cmake ${{ matrix.mode }} --preset ci-ubuntu
cmake --build build/ --parallel 2
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j2

View File

@ -0,0 +1,38 @@
name: build-ubuntu-latest
on: [push, pull_request]
jobs:
linux:
timeout-minutes: 60
strategy:
matrix:
compiler:
- { pkg: g++, exe: 'g++', version: 10 }
- { pkg: g++, exe: 'g++', version: 11 }
- { pkg: g++, exe: 'g++', version: 12 }
- { pkg: clang, exe: 'clang++', version: 12 }
- { pkg: clang, exe: 'clang++', version: 13 }
- { pkg: clang, exe: 'clang++', version: 14 }
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }}
run: |
sudo apt-get update --fix-missing
sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }}
- name: Compile tests
env:
CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }}
run: |
cmake ${{ matrix.mode }} --preset ci-ubuntu
cmake --build build/ --parallel 2
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j2

22
.github/workflows/build-win.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: build-win
on: [push, pull_request]
jobs:
windows:
timeout-minutes: 60
runs-on: windows-latest
strategy:
matrix:
generator: [Visual Studio 17 2022]
mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
run: |
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF -DCMAKE_CXX_FLAGS=/W1 -G"${{ matrix.generator }}" ..
cmake --build . -j 2

33
.github/workflows/coverage.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: coverage
on: [push, pull_request]
jobs:
codecov:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXXFLAGS: "-O0 --coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
CXX: g++
run: |
cmake -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j4
- name: Upload coverage to Codecov
working-directory: build
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: |
wget https://codecov.io/bash -O codecov
chmod +x codecov
./codecov -t $CODECOV_TOKEN -B $GITHUB_REF -s .

32
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: deploy
on:
push:
tags:
- v*
jobs:
conan:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: docker://conanio/gcc8
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@master
with:
version: 3.7
- name: Install
run: |
pip install --upgrade wheel
pip install conan_package_tools
- name: Deploy
env:
CONAN_LOGIN_USERNAME: ${{ secrets.CONAN_LOGIN_USERNAME }}
CONAN_PASSWORD: ${{ secrets.CONAN_PASSWORD }}
CONAN_UPLOAD: ${{ secrets.CONAN_UPLOAD }}
CONAN_GCC_VERSIONS: 8
run: |
python .conan/build.py

30
.github/workflows/sanitizer.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: sanitizer
on: [push, pull_request]
jobs:
clang:
timeout-minutes: 15
strategy:
matrix:
compiler: [clang++]
sanitizer: [ASAN, UBSAN]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXX: ${{ matrix.compiler }}
run: |
cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -DUVW_USE_${{ matrix.sanitizer }}=ON -Dlibuv_buildtests=OFF ..
make -j2
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j2

78
.github/workflows/tools.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: tools
on:
push:
branches:
- tools
jobs:
iwyu:
timeout-minutes: 60
env:
IWYU: "0.22"
LLVM: "18"
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install llvm/clang
# see: https://apt.llvm.org/
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM main"
sudo apt update
sudo apt remove -y "llvm*"
sudo apt remove -y "libclang-dev*"
sudo apt remove -y "clang*"
sudo apt install -y llvm-$LLVM-dev
sudo apt install -y libclang-$LLVM-dev
sudo apt install -y clang-$LLVM
- name: Compile iwyu
# see: https://github.com/include-what-you-use/include-what-you-use
working-directory: build
run: |
git clone https://github.com/include-what-you-use/include-what-you-use.git --branch $IWYU --depth 1
mkdir include-what-you-use/build
cd include-what-you-use/build
cmake -DCMAKE_C_COMPILER=clang-$LLVM \
-DCMAKE_CXX_COMPILER=clang++-$LLVM \
-DCMAKE_INSTALL_PREFIX=./ \
..
make -j4
bin/include-what-you-use --version
- name: Compile tests
working-directory: build
run: |
export PATH=$PATH:${GITHUB_WORKSPACE}/build/include-what-you-use/build/bin
cmake -DUVW_BUILD_TESTING=ON \
-Dlibuv_buildtests=OFF \
-DCMAKE_C_COMPILER=clang-$LLVM \
-DCMAKE_CXX_COMPILER=clang++-$LLVM \
-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=${GITHUB_WORKSPACE}/uvw.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--verbose=1" \
..
make -j4
clang-tidy:
timeout-minutes: 60
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Compile tests
working-directory: build
env:
CXX: clang++
run: |
cmake -DUVW_BUILD_TESTING=ON -DUVW_USE_CLANG_TIDY=ON -Dlibuv_buildtests=OFF ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest -C Debug -j4

9
.gitignore vendored
View File

@ -1,2 +1,9 @@
# QtCreator
*.user
CMakeSettings.json
.conan/test_package/build
cmake-build-debug/
.idea/
.vs/
.vscode/
.cache/
out/

View File

@ -1,52 +0,0 @@
language: cpp
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: COMPILER=g++-5
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6']
env: COMPILER=g++-6
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: COMPILER=clang++-3.8
- os: osx
osx_image: xcode7.3
compiler: clang
env: COMPILER=clang++
- os: osx
osx_image: xcode8
compiler: clang
env: COMPILER=clang++
notifications:
email:
on_success: never
on_failure: always
install:
- echo ${PATH}
- ./travis.sh
- cmake --version
- export CXX=${COMPILER}
- echo ${CXX}
- ${CXX} --version
- ${CXX} -v
script:
- mkdir -p build && cd build
- cmake .. && make -j4
- CTEST_OUTPUT_ON_FAILURE=1 make test

33
AUTHORS
View File

@ -1,14 +1,29 @@
# Author
Michele Caini aka skypjack
skypjack
# Collaborators
morbo84
stefanofiorentino
# Contributors
Federico Bertolucci aka lessness
Luca Martini aka lordlukas
Elia Mazzuoli aka Zikoel
Francesco De Felice aka fradefe
Tushar Maheshwari aka tusharpm
Paolo Monteverde aka morbo84
Jan Vcelak aka fcelda
Raoul Hecky aka raoul
lessness
lordlukas
lpmi-13
Zikoel
fradefe
tusharpm
fcelda
raoul
filonik
yisonPylkita
Miigon
slyshykO
bmagistro
richardbmx
wnsgml972
ffontaine
elindsey
erez-o

View File

@ -2,164 +2,263 @@
# uvw
#
cmake_minimum_required(VERSION 3.13)
#
# Building in-tree is not allowed (we take care of your craziness).
#
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the source code and call cmake from there. Thank you.")
endif()
#
# Project configuration
#
set(UVW_VERSION_MAJOR 3)
set(UVW_VERSION_MINOR 5)
set(UVW_VERSION_PATCH 0)
project(uvw)
cmake_minimum_required(VERSION 3.4)
project(
uvw
VERSION ${UVW_VERSION_MAJOR}.${UVW_VERSION_MINOR}.${UVW_VERSION_PATCH}
DESCRIPTION "Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available also as static library!"
HOMEPAGE_URL "https://github.com/skypjack/uvw"
LANGUAGES C CXX
)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif(NOT CMAKE_BUILD_TYPE)
endif()
set(PROJECT_NAME "uvw")
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 0)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
set(SETTINGS_ORGANIZATION "Michele Caini")
set(SETTINGS_APPLICATION ${PROJECT_NAME})
set(PROJECT_AUTHOR "Michele Caini")
set(PROJECT_YEAR_COPYRIGHT "2017")
set(PROJECT_AUTHOR_EMAIL "michele.caini@gmail.com")
option(UVW_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." ON)
option(UVW_USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF)
option(UVW_USE_UBSAN "Use address sanitizer by adding -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer flags" OFF)
option(UVW_USE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF)
option(UVW_BUILD_LIBS "Prepare targets for static library rather than for a header-only library." OFF)
option(UVW_BUILD_SHARED_LIB "Prepare targets for shared library rather than for a header-only library." OFF)
option(UVW_FIND_LIBUV "Try finding libuv library development files in the system" OFF)
set(PROJECT_BUILD_MESSAGE ${PROJECT_NAME} " v" ${PROJECT_VERSION} " (" ${CMAKE_BUILD_TYPE} ")")
set(COPYRIGHT_BUILD_MESSAGE "Copyright (c) " ${PROJECT_YEAR_COPYRIGHT} " " ${PROJECT_AUTHOR} " <" ${PROJECT_AUTHOR_EMAIL} ">")
if(UVW_BUILD_SHARED_LIB)
set(UVW_BUILD_LIBS BOOL:ON)
endif()
message("*")
message("* " ${PROJECT_BUILD_MESSAGE})
message("* " ${COPYRIGHT_BUILD_MESSAGE})
message("*")
#
# Compiler stuff
#
if(APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,dynamic_lookup")
else(APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
endif(APPLE)
if(NOT WIN32 AND UVW_USE_LIBCPP)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif(NOT WIN32)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os -DRELEASE")
cmake_push_check_state()
add_definitions(
-DPROJECT_NAME=${PROJECT_NAME}
-DPROJECT_VERSION=${PROJECT_VERSION}
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libc++")
check_cxx_source_compiles("
#include<type_traits>
int main() { return std::is_same_v<int, char>; }
" UVW_HAS_LIBCPP)
if(NOT UVW_HAS_LIBCPP)
message(WARNING "The option UVW_USE_LIBCPP is set (by default) but libc++ is not available. The flag will not be added to the target.")
endif()
cmake_pop_check_state()
endif()
if(UVW_USE_CLANG_TIDY)
find_program(UVW_CLANG_TIDY_EXECUTABLE "clang-tidy")
if(NOT UVW_CLANG_TIDY_EXECUTABLE)
message(VERBOSE "The option UVW_USE_CLANG_TIDY is set but clang-tidy executable is not available.")
endif()
endif()
# Required minimal libuv version
set(UVW_LIBUV_VERSION 1.49.0)
function(fetch_libuv)
if (UVW_FETCH_LIBUV)
include(FetchContent)
FetchContent_Declare(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG "v${UVW_LIBUV_VERSION}"
GIT_SHALLOW 1
)
FetchContent_GetProperties(libuv)
if(NOT libuv_POPULATED)
FetchContent_Populate(libuv)
add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
if(UVW_BUILD_SHARED_LIB)
add_library(uv::uv-shared ALIAS uv)
set_target_properties(uv PROPERTIES POSITION_INDEPENDENT_CODE 1)
else()
add_library(uv::uv-static ALIAS uv_a)
set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif()
endif(UVW_FETCH_LIBUV)
endfunction()
function(use_libuv)
set(UVW_FETCH_LIBUV_DEFAULT ON)
if (UVW_FIND_LIBUV)
find_package(libuv ${LIBUV_VERSION} QUIET)
if (libuv_FOUND)
add_library(uv::uv-shared ALIAS uv)
set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via cmake")
else(libuv_FOUND)
find_package(PkgConfig QUIET)
if (PkgConfig_FOUND)
pkg_check_modules(libuv IMPORTED_TARGET libuv>=${LIBUV_VERSION})
if (libuv_FOUND)
add_library(uv::uv-shared ALIAS PkgConfig::libuv)
set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via pkg-config")
endif(libuv_FOUND)
endif(PkgConfig_FOUND)
endif(libuv_FOUND)
endif(UVW_FIND_LIBUV)
option(UVW_FETCH_LIBUV "Fetch the libuv repo using CMake FetchContent facility" ${UVW_FETCH_LIBUV_DEFAULT})
fetch_libuv()
endfunction()
#
# Add uvw target
#
include(GNUInstallDirs)
if(UVW_BUILD_LIBS)
use_libuv()
add_subdirectory(src)
file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp)
else()
add_library(uvw INTERFACE)
add_library(uvw::uvw ALIAS uvw)
target_compile_features(uvw INTERFACE cxx_std_17)
target_include_directories(
uvw
INTERFACE
$<BUILD_INTERFACE:${uvw_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(UVW_USE_ASAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address>)
endif()
if(UVW_USE_UBSAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>)
target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif()
if(UVW_CLANG_TIDY_EXECUTABLE)
set(CMAKE_CXX_CLANG_TIDY "${UVW_CLANG_TIDY_EXECUTABLE};--config-file=${uvw_SOURCE_DIR}/.clang-tidy;--header-filter=${uvw_SOURCE_DIR}/src/uvw/.*")
endif()
if(UVW_HAS_LIBCPP)
target_compile_options(uvw BEFORE INTERFACE -stdlib=libc++)
endif()
file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp)
endif()
#
# Install targets
#
install(
FILES ${HEADERS}
COMPONENT ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/uvw
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(
FILES src/uvw.hpp
COMPONENT ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
#
# CMake configuration
# Install targets
#
set(PROJECT_CMAKE_MODULES cmake/modules)
set(PROJECT_CMAKE_IN cmake/in)
set(PROJECT_BUILD_DIR build)
set(PROJECT_DEPS_DIR deps)
set(PROJECT_DOCS_DIR docs)
set(PROJECT_SRC_DIR src)
set(PROJECT_TEST_DIR test)
if (UVW_BUILD_LIBS)
set_target_properties(
uvw PROPERTIES
VERSION ${UVW_VERSION_MAJOR}.${UVW_VERSION_MINOR}.${UVW_VERSION_PATCH}
SOVERSION ${UVW_VERSION_MAJOR}
)
endif()
set(PROJECT_RUNTIME_OUTPUT_DIRECTORY bin)
set(
CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${CMAKE_SOURCE_DIR}/${PROJECT_CMAKE_MODULES}
install(
EXPORT uvwConfig
NAMESPACE uvw::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/uvw
)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_RUNTIME_OUTPUT_DIRECTORY})
#
# Enable test support using ctest
#
enable_testing()
#
# Referenced packages
#
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(Doxygen 1.8)
find_package(LibRt)
#
# Download and unpack dependencies
#
set(GOOGLETEST_DEPS_DIR ${CMAKE_SOURCE_DIR}/${PROJECT_DEPS_DIR}/googletest)
set(LIBUV_DEPS_DIR ${CMAKE_SOURCE_DIR}/${PROJECT_DEPS_DIR}/libuv)
# gtest, gtest_main, gmock and gmock_main targets are available from now on
configure_file(${PROJECT_CMAKE_IN}/googletest.in ${GOOGLETEST_DEPS_DIR}/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${GOOGLETEST_DEPS_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${GOOGLETEST_DEPS_DIR})
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(${GOOGLETEST_DEPS_DIR}/src ${GOOGLETEST_DEPS_DIR}/build)
configure_file(${PROJECT_CMAKE_IN}/libuv.in ${LIBUV_DEPS_DIR}/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${LIBUV_DEPS_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${LIBUV_DEPS_DIR})
include_directories(${LIBUV_DEPS_DIR}/src/include)
find_library(libuv_static NAMES libuv.a libuv PATHS ${LIBUV_DEPS_DIR}/src PATH_SUFFIXES .libs Release NO_DEFAULT_PATH)
find_library(libuv_shared NAMES uv libuv PATHS ${LIBUV_DEPS_DIR}/src PATH_SUFFIXES .libs Release NO_DEFAULT_PATH)
#
# Referenced directories and targets
#
if(${DOXYGEN_FOUND})
add_subdirectory(${PROJECT_DOCS_DIR})
endif(${DOXYGEN_FOUND})
add_subdirectory(${PROJECT_TEST_DIR})
#
# Keep your stuff and go further away, foolish.
#
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR ${PROJECT_AUTHOR})
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "uvw")
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME}-src)
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE)
set(CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/README.md)
set(CPACK_GENERATOR TGZ)
set(CPACK_SOURCE_GENERATOR TGZ)
set(CPACK_PACKAGING_INSTALL_DIRECTORY "uvw-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
include(CPack)
#
# I use QtCreator and I need the lines below, so do not ask. :-)
#
file(
GLOB_RECURSE PROJECT_FILES FOLLOW_SYMLINKS
*.txt *.c *.cpp *.hpp *.h *.in *.cmake *.sh *.md *.yml *.bat AUTHORS LICENSE
install(
TARGETS uvw
EXPORT uvwConfig
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
add_custom_target(
QTCREATOR_FALLBACK ALL
COMMENT "Feel free to ignore this target, but please do not remove it."
SOURCES ${PROJECT_FILES}
)
if(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
# libuv is only fetched when both above conditions are true
install(DIRECTORY ${libuv_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/uvw/uv/include)
if (UVW_BUILD_SHARED_LIB)
install(TARGETS uv EXPORT uvwConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
else()
install(TARGETS uv_a EXPORT uvwConfig ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
endif()
endif(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
export(EXPORT uvwConfig)
### Testing
option(UVW_BUILD_TESTING "Enable testing with ctest." OFF)
if(UVW_BUILD_TESTING)
option(UVW_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
if (NOT UVW_BUILD_LIBS)
use_libuv()
endif()
enable_testing()
add_subdirectory(test)
endif()
#
# Documentation
#
option(UVW_BUILD_DOCS "Enable building with documentation." OFF)
if(UVW_BUILD_DOCS)
find_package(Doxygen 1.10)
if(DOXYGEN_FOUND)
add_subdirectory(docs)
endif()
endif()

59
CMakePresets.json Normal file
View File

@ -0,0 +1,59 @@
{
"version": 2,
"cmakeMinimumRequired": {
"major": 3,
"minor": 13,
"patch": 0
},
"configurePresets": [
{
"name": "cmake-pedantic",
"description": "Enables all CMake warnings.`",
"hidden": true,
"warnings": {
"dev": true,
"deprecated": true,
"uninitialized": true,
"unusedCli": true,
"systemVars": false
}
},
{
"name": "dev-mode",
"hidden": true,
"description": "Common (non-OS specific) mode for development",
"inherits": "cmake-pedantic",
"cacheVariables": {
"UVW_BUILD_TESTING": true,
"libuv_buildtests": false
}
},
{
"name": "flags-linux",
"hidden": true,
"description": "Compiler flags for GNU and Clang compilers. When compiling in DEBUG mode, all warnings will be converted into errors.",
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wimplicit-fallthrough -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast",
"CMAKE_CXX_FLAGS_DEBUG": "-Werror"
}
},
{
"name": "ci-linux",
"generator": "Unix Makefiles",
"hidden": true,
"inherits": ["flags-linux"],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "ci-build",
"binaryDir": "${sourceDir}/build",
"hidden": true
},
{
"name": "ci-ubuntu",
"inherits": ["ci-build", "ci-linux", "dev-mode"]
}
]
}

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2017 Michele Caini
Copyright (c) 2016-2024 Michele Caini
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

451
README.md
View File

@ -1,32 +1,49 @@
![cynny-logo](https://web.cynny.com/live/static/favicon/favicon-16.png) **Sponsored and contributed by [Cynny SpA](https://www.cynny.com/).**
![uvw - libuv wrapper in modern C++](https://user-images.githubusercontent.com/1812216/46069406-c977a600-c17b-11e8-9a47-9bba6f412c57.png)
# uvw - libuv wrapper in modern C++
[![Build Status](https://github.com/skypjack/uvw/workflows/build/badge.svg)](https://github.com/skypjack/uvw/actions)
[![Coverage](https://codecov.io/gh/skypjack/uvw/branch/master/graph/badge.svg)](https://codecov.io/gh/skypjack/uvw)
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue)](https://skypjack.github.io/uvw/)
[![Vcpkg port](https://img.shields.io/vcpkg/v/uvw)](https://vcpkg.link/ports/uvw)
[![Gitter chat](https://badges.gitter.im/skypjack/uvw.png)](https://gitter.im/skypjack/uvw)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/skypjack)
[![Build Status](https://travis-ci.org/skypjack/uvw.svg?branch=master)](https://travis-ci.org/skypjack/uvw)
[![Build status](https://ci.appveyor.com/api/projects/status/m5ndm8gnu8isg2to?svg=true)](https://ci.appveyor.com/project/skypjack/uvw)
[![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)
Do you have a **question** that doesn't require you to open an issue? Join the
[gitter channel](https://gitter.im/skypjack/uvw).<br/>
If you use `uvw` and you want to say thanks or support the project, please
**consider becoming a
[sponsor](https://github.com/users/skypjack/sponsorship)**.<br/>
You can help me make the difference.
[Many thanks](https://skypjack.github.io/sponsorship/) to those who supported me
and still support me today.
# Introduction
`uvw` is a header-only, event based, tiny and easy to use *libuv* wrapper in modern C++.<br/>
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/>
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/>
As an example, a *handle* should be initialized before any other operation and closed once it is no longer in use.
`uvw` started as a header-only, event based, tiny and easy to use wrapper for
[`libuv`](https://github.com/libuv/libuv) written in modern C++.<br/>
Now it's finally available also as a compilable static library.
The basic idea is to wrap the *C-ish* interface of `libuv` behind a graceful C++
API.<br/>
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 which are used with `libuv`.<br/>
As an example, a *handle* should be initialized before any other operation and
closed once it is no longer in use.
## Code Example
```
```cpp
#include <uvw.hpp>
#include <memory>
void listen(uvw::Loop &loop) {
std::shared_ptr<uvw::TcpHandle> tcp = loop.resource<uvw::TcpHandle>();
void listen(uvw::loop &loop) {
std::shared_ptr<uvw::tcp_handle> tcp = loop.resource<uvw::tcp_handle>();
tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TcpHandle &srv) {
std::shared_ptr<uvw::TcpHandle> client = srv.loop().resource<uvw::TcpHandle>();
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::shared_ptr<uvw::tcp_handle> client = srv.parent().resource<uvw::tcp_handle>();
client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::TcpHandle &) { ptr->close(); });
client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TcpHandle &client) { client.close(); });
client->on<uvw::close_event>([ptr = srv.shared_from_this()](const uvw::close_event &, uvw::tcp_handle &) { ptr->close(); });
client->on<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
srv.accept(*client);
client->read();
@ -36,12 +53,12 @@ void listen(uvw::Loop &loop) {
tcp->listen();
}
void conn(uvw::Loop &loop) {
auto tcp = loop.resource<uvw::TcpHandle>();
void conn(uvw::loop &loop) {
auto tcp = loop.resource<uvw::tcp_handle>();
tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* handle errors */ });
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { /* handle errors */ });
tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::TcpHandle &tcp) {
tcp->on<uvw::connect_event>([](const uvw::connect_event &, uvw::tcp_handle &tcp) {
auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
tcp.write(std::move(dataWrite), 2);
tcp.close();
@ -51,7 +68,7 @@ void conn(uvw::Loop &loop) {
}
int main() {
auto loop = uvw::Loop::getDefault();
auto loop = uvw::loop::get_default();
listen(*loop);
conn(*loop);
loop->run();
@ -60,7 +77,8 @@ int main() {
## Motivation
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.
The main reason for which `uvw` has been written is the fact that there does not
exist a valid `libuv` wrapper in C++. That's all.
# Build Instructions
@ -68,181 +86,303 @@ The main reason for which `uvw` has been written is the fact that it does not ex
To be able to use `uvw`, users must provide the following system-wide tools:
* A full-featured compiler that supports at least C++14.
* `libuv` (which version depends on the tag of `uvw` in use).
* A full-featured compiler that supports at least C++17.
* `libuv` (which version depends on the tag of `uvw` in use)
* If you use `meson`, libuv will be downloaded for you
The requirements below are mandatory to compile the tests and to extract the documentation:
The requirements below are mandatory to compile the tests and to extract the
documentation:
* CMake version 3.4 or later.
* CMake version 3.13 or later.
* Doxygen version 1.8 or later.
Note that `libuv` is part of the dependencies of the project and it will be cloned by `cmake` (see below for further details).<br/>
Because of that, users have not to install it to compile and execute the tests.
Note that `libuv` is part of the dependencies of the project and may be cloned
by `CMake` in some cases (see below for further details).<br/>
Because of that, users don't have to install it to run the tests or when `uvw`
libraries are compiled through `CMake`.
## Meson
You can use `uvw` with [meson](https://mesonbuild.com/) by simply adding it to
your `subprojects` directory in your project.
To compile `uvw` from source without using it as a subproject, in the `uvw`
source directory, run:
* `$ meson setup build`
* If you want a static library, add `--default-library=static`
* `$ cd build`
* `$ meson compile`
## Library
`uvw` is a header-only library.<br/>
This means that including the `uvw.hpp` header or one of the other `uvw/*.hpp` headers is enough to use it.<br/>
`uvw` is a dual-mode library. It can be used in its header-only form or as a
compiled static library.<br/>
The following sections describe what to do in both cases to get `uvw` up and
runningin your own project.
### Header-only
To use `uvw` as a header-only library, all is needed is to include the `uvw.hpp`
header or one of the other `uvw/*.hpp` files.<br/>
It's a matter of adding the following line at the top of a file:
#include <uvw.hpp>
```cpp
#include <uvw.hpp>
```
Then pass the proper `-I` argument to the compiler to add the `src` directory to the include paths.<br/>
Note that users are demanded to correctly setup include directories and libraries search paths for *libuv*.
Then pass the proper `-I` argument to the compiler to add the `src` directory to
the include paths.<br/>
Note that users are required to correctly setup the include directories and
libraries search paths for `libuv` in this case.
When used through `CMake`, the `uvw::uvw` target is exported for convenience.
### Static
To use `uvw` as a compiled library, set the `UVW_BUILD_LIBS` options in cmake
before including the project.<br/>
This option triggers the generation of a targets named
`uvw::uvw-static`. The matching version of `libuv` is also
compiled and exported as `uv::uv-static` for convenience.
In case you don't use or don't want to use `CMake`, you can still compile all
`.cpp` files and include all `.h` files to get the job done. In this case, users
are required to correctly setup the include directories and libraries search
paths for `libuv`.
## Versioning
Starting with tag _v1.12.0_ of `libuv`, `uvw` follows the [semantic versioning](http://semver.org/) scheme.<br/>
The problem is that any version of `uvw` also requires to track explicitly the version of `libuv` to which it is bound.<br/>
Because of that, the latter wil be appended to the version of `uvw`. As an example:
Starting with tag _v1.12.0_ of `libuv`, `uvw` follows the
[semantic versioning](http://semver.org/) scheme.<br/>
The problem is that any version of `uvw` also requires to track explicitly the
version of `libuv` to which it is bound.<br/>
Because of that, the latter wil be appended to the version of `uvw`. As an
example:
vU.V.W_libuv-vX.Y
In particular, the following applies:
* _U.V.W_ are major, minor and patch versions of `uvw`.
* _X.Y_ is the version of `libuv` to which to refer (where any patch version is valid).
* _X.Y_ is the version of `libuv` to which to refer (where any patch version is
valid).
In other terms, tags will look like this from now on:
v1.0.0_libuv-v1.12
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/>
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/>
## Documentation
### API Reference
The documentation is based on [`doxygen`](http://www.stack.nl/~dimitri/doxygen/). To build it:
The documentation is based on
[`doxygen`](https://www.doxygen.nl/). To build it:
* `$ cd build`
* `$ cmake ..`
* `$ make docs`
The API reference will be created in HTML format within the directory `build/docs/html`.<br/>
The API reference will be created in HTML format within the directory
`build/docs/html`.<br/>
To navigate it with your favorite browser:
* `$ cd build`
* `$ your_favorite_browser docs/html/index.html`
### Crash Course
The same version is also available [online](https://skypjack.github.io/uvw/)
for the latest release, that is the last stable tag.
#### Vademecum
### Note
There is only one rule when using `uvw`: always initialize the resources and terminate them.
The documentation is mostly inspired by the official
[libuv API documentation](http://docs.libuv.org/en/v1.x/) for obvious
reasons.
## Tests
To compile and run the tests, `uvw` requires `libuv` and `googletest`.<br/>
`CMake` will download and compile both the libraries before compiling anything
else.
To build the tests:
* `$ cd build`
* `$ cmake .. -DUVW_BUILD_TESTING=ON`
* `$ make`
* `$ ctest -j4 -R uvw`
Omit `-R uvw` if you also want to test `libuv` and other dependencies.
# Crash Course
## Vademecum
There is only one rule when using `uvw`: always initialize the resources and
terminate them.
Resources belong mainly to two families: _handles_ and _requests_.<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.
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.
The following sections will explain in short what it means to initialize and terminate these kinds of resources.
The following sections will explain in short what it means to initialize and
terminate these kinds of resources.<br/>
For more details, please refer to the
[online documentation](https://skypjack.github.io/uvw/).
#### Handles
## Handles
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/>
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 *always close your handles*. It's as simple as calling the `close` member function on them.
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/>
On the other side, handles keep themselves alive until one explicitly closes
them. Because of that, memory usage will grow if users simply forget about a
handle.<br/>
Therefore the rule quickly becomes *always close your handles*. It's as simple
as calling the `close` member function on them.
#### Requests
## Requests
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/>
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 *feel free to make a request and forget about it*. It's as simple as calling a member function on them.
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/>
Requests will keep themselves alive as long as they are bound to unfinished
underlying activities. This means that users don't have to discard a
request explicitly .<br/>
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.
#### The Loop and the Resource
## The Loop and the Resource
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:
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:
auto loop = uvw::Loop::getDefault();
```cpp
auto loop = uvw::loop::get_default();
```
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/>
Loops can be started using the `run` member function. The two calls below are equivalent:
Note that loop objects don't require being closed explicitly, even if they offer
the `close` member function in case a user wants to do that.<br/>
Loops can be started using the `run` member function. The two calls below are
equivalent:
loop->run();
loop->run<uvw::Loop::Mode::DEFAULT>
```cpp
loop->run();
loop->run(uvw::loop::run_mode::DEFAULT);
```
Available modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the documentation of *libuv* for further details.
Available modes are: `DEFAULT`, `ONCE`, `NOWAIT`. Please refer to the
documentation of `libuv` for further details.
In order to create a resource and to bind it to the given loop, just do the following:
In order to create a resource and to bind it to the given loop, just do the
following:
auto tcp = loop.resource<uvw::TcpHandle>();
```cpp
auto tcp = loop->resource<uvw::tcp_handle>();
```
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:
The line above creates and initializes a tcp handle, then a shared pointer to
that resource is returned.<br/>
Users should check if pointers have been correctly initialized: in case of
errors, they won't be.<br/>
It also is possible to create uninitialized resources to init later on as:
auto tcp = TcpHandle::create(loop);
tcp->init();
```cpp
auto tcp = loop->uninitialized_resource<uvw::tcp_handle>();
tcp->init();
```
Pretty annoying indeed. Using a loop is the recommended approach.
The resources also accept arbitrary user-data that won't be touched in any case.<br/>
All resources also accept arbitrary user-data that won't be touched in any
case.<br/>
Users can set and get them through the `data` member function as it follows:
resource->data(std::make_shared<int>(42));
std::shared_ptr<void> data = resource->data();
```cpp
resource->data(std::make_shared<int>(42));
std::shared_ptr<void> data = resource->data();
```
Resources expect a `std::shared_pointer<void>` and return it, therefore any kind of data is welcome.<br/>
Users can explicitly specify a type other than `void` when calling the `data` member function:
Resources expect a `std::shared_pointer<void>` and return it, therefore any kind
of data is welcome.<br/>
Users can explicitly specify a type other than `void` when calling the `data`
member function:
std::shared_ptr<int> data = resource->data<int>();
```cpp
std::shared_ptr<int> data = resource->data<int>();
```
Remember from the previous section that a handle will keep itself alive until one invokes the `close` 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:
Remember from the previous section that a handle will keep itself alive until
one invokes the `close` member function on it.<br/>
To know what are the handles that are still alive and bound to a given loop,
there exists the `walk` member function. It returns handles with their types.
Therefore, the use of `overloaded` is recommended to be able to intercept all
types of interest:
loop.walk([](uvw::BaseHandle &){ /* application code here */ });
```cpp
handle.parent().walk(uvw::overloaded{
[](uvw::timer_handle &h){ /* application code for timers here */ },
[](auto &&){ /* ignore all other types */ }
});
```
`BaseHandle` exposes a few methods and cannot be used to know the original type of the handle.<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:
This function can also be used for a completely generic approach. For example,
all the pending handles can be closed easily as it follows:
loop.walk([](uvw::BaseHandle &h){ h.close(); });
```cpp
loop->walk([](auto &&h){ h.close(); });
```
No need to keep track of them.
To know what are the available resources' types, please refer the API reference.
## The event-based approach
#### The event-based approach
`uvw` offers an event-based approach where resources are small event emitters to
which listeners are attached.<br/>
Attaching listeners to resources is the recommended way to receive notifications
about their operations.<br/>
Listeners are callable objects of type `void(event_type &, resource_type &)`,
where:
For `uvw` 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 `void(EventType &, ResourceType &)`, where:
* `EventType` is the type of the event for which they have been designed.
* `ResourceType` is the type of the resource that has originated the event.
* `event_type` is the type of the event for which they have been designed.
* `resource_type` is the type of the resource that has originated the event.
It means that the following function types are all valid:
* `void(EventType &, ResourceType &)`
* `void(const EventType &, ResourceType &)`
* `void(EventType &, const ResourceType &)`
* `void(const EventType &, const ResourceType &)`
* `void(event_type &, resource_type &)`
* `void(const event_type &, resource_type &)`
* `void(event_type &, const resource_type &)`
* `void(const event_type &, const resource_type &)`
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.
Please note that there is no need to keep around references to the resources,
since they pass themselves as an argument whenever an event is published.<br/>
The `on` member function is the way to go to register long-running listeners:
There exist two methods to attach an event to a resource:
```cpp
resource.on<event_type>(listener)
```
* `resource.once<EventType>(listener)`: the listener will be automatically removed after the first event of the given type.
* `resource.on<EventType>(listener)`: to be used for long-running listeners.
To know if a listener exists for a given type, the class offers a `has` function
template. Similarly, the `reset` function template is be used to reset and thus
disconnect listeners, if any. A non-template version of `reset` also exists to
clear an emitter as a whole.
Both of them return an object of type `ResourceType::Connection` (as an example, `TcpHandle::Connection`).<br/>
A connection object can be used later as an argument to the `erase` member function of the resource to remove the listener.<br/>
There exists also the `clear` member function to drop all the listeners at once.
Almost all the resources use to emit `ErrorEvent` events in case of errors.<br/>
All the other events are specific for the given resource and documented in the API reference.
Almost all the resources emit `error_event` in case of errors.<br/>
All the other events are specific for the given resource and documented in the
API reference.
The code below shows how to create a simple tcp server using `uvw`:
```
auto loop = uvw::Loop::getDefault();
auto tcp = loop.resource<uvw::TcpHandle>();
```cpp
auto loop = uvw::loop::get_default();
auto tcp = loop->resource<uvw::tcp_handle>();
tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TcpHandle &) { /* something went wrong */ });
tcp->on<uvw::error_event>([](const uvw::error_event &, uvw::tcp_handle &) { /* something went wrong */ });
tcp->on<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TcpHandle &srv) {
std::shared_ptr<uvw::TcpHandle> client = srv.loop().resource<uvw::TcpHandle>();
client->once<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TcpHandle &client) { client.close(); });
client->on<uvw::DataEvent>([](const uvw::DataEvent &, uvw::TcpHandle &) { /* data received */ });
tcp->on<uvw::listen_event>([](const uvw::listen_event &, uvw::tcp_handle &srv) {
std::shared_ptr<uvw::tcp_handle> client = srv.parent().resource<uvw::tcp_handle>();
client->on<uvw::end_event>([](const uvw::end_event &, uvw::tcp_handle &client) { client.close(); });
client->on<uvw::data_event>([](const uvw::data_event &, uvw::tcp_handle &) { /* data received */ });
srv.accept(*client);
client->read();
});
@ -251,49 +391,66 @@ tcp->bind("127.0.0.1", 4242);
tcp->listen();
```
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/>
It's suffice to explicitly specify `uvw::IPv6` as the underlying protocol to use it.
Note also that `uvw::tcp_handle` already supports _IPv6_ out-of-the-box.<br/>
The API reference is the recommended documentation for further details about
resources and their methods.
The API reference is the recommended documentation for further details about resources and their methods.
## Going raw
## Tests
In case users need to use functionalities not wrapped yet by `uvw` or if they
want to get the underlying data structures as defined by `libuv` for some other
reasons, almost all the classes in `uvw` give direct access to them.<br/>
Please, note that this functions should not be used directly unless users know
exactly what they are doing and what are the risks. Going raw is dangerous,
mainly because the lifetime management of a loop, a handle or a request is
completely controlled by the library and working around it could quickly break
things.
To compile and run the tests, `uvw` requires *libuv* and *googletest*.<br/>
`cmake` will download and compile both the libraries before to compile anything else.
That being said, _going raw_ is a matter of using the `raw` member functions:
To build the tests:
```cpp
auto loop = uvw::loop::get_default();
auto tcp = loop->resource<uvw::tcp_handle>();
* `$ cd build`
* `$ cmake ..`
* `$ make`
* `$ make test`
uv_loop_t *raw = loop->raw();
uv_tcp_t *handle = tcp->raw();
```
Go the raw way at your own risk, but do not expect any support in case of bugs.
# Related projects
Interested in additional tools and libraries that build upon `uvw`? You might
find the following useful then:
- [`uvw_net`](https://github.com/mincequi/uvw_net): a networking library with a
collection of clients (HTTP/Modbus/SunSpec) that also includes discovery
impementations like dns-sd/mdns.
Feel free to add your tool to the list if you like.
# Contributors
If you want to contribute, please send patches as pull requests against the branch master.<br/>
Check the [contributors list](https://github.com/skypjack/uvw/blob/master/AUTHORS) to see who has partecipated so far.
# Projects that use `uvw`
Below an incomplete list of projects that use `uvw`:
* Internal tools (not publicly available) at [Cynny SpA](https://www.morphcast.com/) and [Cynny Space](http://www.cynnyspace.com/).
* [Calaos.fr](https://www.calaos.fr/en/) (Open source home automation) on [GitHub](https://github.com/calaos).
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.
If you want to contribute, please send patches as pull requests against the
branch master.<br/>
Check the
[contributors list](https://github.com/skypjack/uvw/blob/master/AUTHORS) to see
who has partecipated so far.
# License
Code and documentation Copyright (c) 2017 Michele Caini.<br/>
Code released under [the MIT license](https://github.com/skypjack/uvw/blob/master/LICENSE).<br/>
Docs released under [Creative Commons](https://github.com/skypjack/uvw/blob/master/docs/LICENSE).
Code and documentation Copyright (c) 2016-2024 Michele Caini.<br/>
Logo Copyright (c) 2018-2021 Richard Caseres.
# Note
Code and documentation released under
[the MIT license](https://github.com/skypjack/uvw/blob/master/LICENSE).<br/>
Logo released under
[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
The documentation is mostly inspired by the official [libuv API documentation](http://docs.libuv.org/en/v1.x/) for obvious reasons.
# Support
# Donation
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/>
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 [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).
If you want to support this project, you can
[offer me](https://github.com/users/skypjack/sponsorship) an espresso.<br/>
If you find that it's not enough, feel free to
[help me](https://www.paypal.me/skypjack) the way you prefer.

5
TODO Normal file
View File

@ -0,0 +1,5 @@
* do not send error events when the return value is enough (still wip)
* also cleanup error event mentions in the doc
* Make all tests pass on all platforms
* add iwyu and clean up everything
* Allocator support

View File

@ -1,22 +0,0 @@
# can use variables like {build} and {branch}
version: 1.0.{build}
image: Visual Studio 2015
environment:
BUILD_DIR: "%APPVEYOR_BUILD_FOLDER%\\build"
platform:
- Win32
configuration:
- Release
before_build:
- cd %BUILD_DIR%
- cmake .. -G"Visual Studio 14 2015"
build:
parallel: true
project: build/uvw.sln
verbosity: minimal

View File

@ -1,19 +0,0 @@
project(googletest-download NONE)
cmake_minimum_required(VERSION 3.4)
include(ExternalProject)
ExternalProject_Add(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
DOWNLOAD_DIR ${GOOGLETEST_DEPS_DIR}
TMP_DIR ${GOOGLETEST_DEPS_DIR}/tmp
STAMP_DIR ${GOOGLETEST_DEPS_DIR}/stamp
SOURCE_DIR ${GOOGLETEST_DEPS_DIR}/src
BINARY_DIR ${GOOGLETEST_DEPS_DIR}/build
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -1,36 +0,0 @@
project(libuv-download NONE)
cmake_minimum_required(VERSION 3.4)
include(ExternalProject)
if(WIN32)
ExternalProject_Add(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG v1.12.0
DOWNLOAD_DIR ${LIBUV_DEPS_DIR}
TMP_DIR ${LIBUV_DEPS_DIR}/tmp
STAMP_DIR ${LIBUV_DEPS_DIR}/stamp
SOURCE_DIR ${LIBUV_DEPS_DIR}/src
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND <SOURCE_DIR>/vcbuild.bat release x86 shared
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
else(WIN32)
ExternalProject_Add(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG v1.12.0
DOWNLOAD_DIR ${LIBUV_DEPS_DIR}
TMP_DIR ${LIBUV_DEPS_DIR}/tmp
STAMP_DIR ${LIBUV_DEPS_DIR}/stamp
SOURCE_DIR ${LIBUV_DEPS_DIR}/src
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND sh <SOURCE_DIR>/autogen.sh && ./configure
BUILD_COMMAND make -j4
INSTALL_COMMAND ""
TEST_COMMAND ""
)
endif(WIN32)

View File

@ -1,32 +0,0 @@
# FindLibRt
# --------
#
# Find the native realtime includes and library.
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module defines the following variables:
#
# ::
#
# LIBRT_INCLUDE_DIRS - where to find time.h, etc.
# LIBRT_LIBRARIES - List of libraries when using librt.
# LIBRT_FOUND - True if realtime library found.
#
# Hints
# ^^^^^
#
# A user may set ``LIBRT_ROOT`` to a realtime installation root to tell this
# module where to look.
find_path(
LIBRT_INCLUDE_DIRS
NAMES time.h
PATHS ${LIBRT_ROOT}/include/
)
find_library(LIBRT_LIBRARIES rt)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibRt DEFAULT_MSG LIBRT_LIBRARIES LIBRT_INCLUDE_DIRS)
mark_as_advanced(LIBRT_INCLUDE_DIRS LIBRT_LIBRARIES)

23
conanfile.py Normal file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from conans import ConanFile
class UVWConan(ConanFile):
name = "uvw"
description = "Header-only, event based, tiny and easy to use libuv wrapper in modern C++"
homepage = "https://github.com/skypjack/uvw"
url = homepage
license = "MIT"
topics = ("conan", "uvw", "libuv", "header-only", "wrapper", "event-loop")
author = "Michele Caini <michele.caini@gmail.com>"
exports = "LICENSE"
exports_sources = "src/*"
no_copy_source = True
requires = "libuv/1.49.0@bincrafters/stable"
def package(self):
self.copy(pattern="LICENSE", dst="licenses")
self.copy(pattern="*.hpp", dst="include", src="src")
def package_id(self):
self.info.header_only()

View File

@ -2,25 +2,22 @@
# Doxygen configuration (documentation)
#
set(TARGET_DOCS docs)
set(DOXY_IN_FILE doxy.in)
set(DOXY_SOURCE_DIRECTORY ${PROJECT_SRC_DIR})
set(DOXY_DEPS_DIRECTORY ${uvw_SOURCE_DIR}/deps)
set(DOXY_SOURCE_DIRECTORY ${uvw_SOURCE_DIR}/src)
set(DOXY_DOCS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(DOXY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(DOXY_CFG_FILE doxy.cfg)
configure_file(${DOXY_IN_FILE} ${DOXY_CFG_FILE} @ONLY)
configure_file(doxy.in doxy.cfg @ONLY)
add_custom_target(
${TARGET_DOCS}
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/${DOXY_CFG_FILE}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
docs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.cfg
WORKING_DIRECTORY ${uvw_SOURCE_DIR}
VERBATIM
SOURCES ${DOXY_IN_FILE}
SOURCES doxy.in
)
install(
DIRECTORY ${DOXY_OUTPUT_DIRECTORY}/html
DESTINATION ${PROJECT_SHARE_OUTPUT_DIRECTORY}/${PROJECT_NAME}-${PROJECT_VERSION}/
DESTINATION share/${PROJECT_NAME}-${PROJECT_VERSION}/
)

View File

@ -1,395 +0,0 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

File diff suppressed because it is too large Load Diff

5
docs/extra.dox Normal file
View File

@ -0,0 +1,5 @@
/**
* @namespace uvw
*
* @brief `uvw` default namespace.
*/

54
meson.build Normal file
View File

@ -0,0 +1,54 @@
project(
'uvw',
'cpp',
version: '3.3.0',
license: 'MIT',
default_options: ['cpp_std=c++17'],
)
libuv_dep = dependency('libuv', version: '1.48.0', required: true)
sources = [
'src/uvw/async.cpp',
'src/uvw/check.cpp',
'src/uvw/dns.cpp',
'src/uvw/emitter.cpp',
'src/uvw/fs.cpp',
'src/uvw/fs_event.cpp',
'src/uvw/fs_poll.cpp',
'src/uvw/idle.cpp',
'src/uvw/lib.cpp',
'src/uvw/loop.cpp',
'src/uvw/pipe.cpp',
'src/uvw/poll.cpp',
'src/uvw/prepare.cpp',
'src/uvw/process.cpp',
'src/uvw/signal.cpp',
'src/uvw/stream.cpp',
'src/uvw/tcp.cpp',
'src/uvw/thread.cpp',
'src/uvw/timer.cpp',
'src/uvw/tty.cpp',
'src/uvw/udp.cpp',
'src/uvw/util.cpp',
'src/uvw/work.cpp',
]
uvw_lib = library(
'uvw',
sources,
include_directories: 'src',
dependencies: [libuv_dep],
cpp_args: ['-DUVW_AS_LIB'],
install: true,
)
uvw_dep = declare_dependency(
include_directories: ['src'],
dependencies: [libuv_dep],
link_with: [uvw_lib],
)
if meson.version().version_compare('>=0.54.0')
meson.override_dependency('uvw', uvw_dep)
endif

82
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,82 @@
#
# Setup libraries
#
function(add_uvw_library LIB_NAME)
target_sources(
${LIB_NAME}
PRIVATE
uvw/async.cpp
uvw/check.cpp
uvw/dns.cpp
uvw/emitter.cpp
uvw/fs.cpp
uvw/fs_event.cpp
uvw/fs_poll.cpp
uvw/idle.cpp
uvw/lib.cpp
uvw/loop.cpp
uvw/pipe.cpp
uvw/poll.cpp
uvw/prepare.cpp
uvw/process.cpp
uvw/signal.cpp
uvw/stream.cpp
uvw/tcp.cpp
uvw/thread.cpp
uvw/timer.cpp
uvw/tty.cpp
uvw/udp.cpp
uvw/util.cpp
uvw/work.cpp
)
set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE 1)
target_compile_definitions(${LIB_NAME} PUBLIC UVW_AS_LIB)
target_compile_features(${LIB_NAME} PUBLIC cxx_std_17)
target_include_directories(
${LIB_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(UVW_USE_ASAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
endif()
if(UVW_USE_UBSAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>)
target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif()
if(UVW_HAS_LIBCPP)
target_compile_options(${LIB_NAME} BEFORE PUBLIC -stdlib=libc++)
endif()
endfunction()
#
# Build and install libraries
#
if (UVW_BUILD_SHARED_LIB)
add_library(uvw SHARED)
add_library(uvw::uvw-shared ALIAS uvw)
# If libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-shared)
endif()
else()
add_library(uvw STATIC)
add_library(uvw::uvw-static ALIAS uvw)
# If libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-static)
endif()
endif()
add_library(uvw::uvw ALIAS uvw)
set_target_properties(uvw PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1)
add_uvw_library(uvw)

View File

@ -1,21 +1,28 @@
#include "uvw/async.hpp"
#include "uvw/check.hpp"
#include "uvw/dns.hpp"
#include "uvw/fs.hpp"
#include "uvw/fs_event.hpp"
#include "uvw/fs_poll.hpp"
#include "uvw/idle.hpp"
#include "uvw/lib.hpp"
#include "uvw/loop.hpp"
#include "uvw/pipe.hpp"
#include "uvw/poll.hpp"
#include "uvw/prepare.hpp"
#include "uvw/process.hpp"
#include "uvw/signal.hpp"
#include "uvw/tcp.hpp"
#include "uvw/thread.hpp"
#include "uvw/timer.hpp"
#include "uvw/tty.hpp"
#include "uvw/udp.hpp"
#include "uvw/util.hpp"
#include "uvw/work.hpp"
#include "uvw/async.h"
#include "uvw/check.h"
#include "uvw/config.h"
#include "uvw/dns.h"
#include "uvw/emitter.h"
#include "uvw/enum.hpp"
#include "uvw/fs.h"
#include "uvw/fs_event.h"
#include "uvw/fs_poll.h"
#include "uvw/handle.hpp"
#include "uvw/idle.h"
#include "uvw/lib.h"
#include "uvw/loop.h"
#include "uvw/pipe.h"
#include "uvw/poll.h"
#include "uvw/prepare.h"
#include "uvw/process.h"
#include "uvw/request.hpp"
#include "uvw/resource.hpp"
#include "uvw/signal.h"
#include "uvw/tcp.h"
#include "uvw/thread.h"
#include "uvw/timer.h"
#include "uvw/tty.h"
#include "uvw/udp.h"
#include "uvw/util.h"
#include "uvw/uv_type.hpp"
#include "uvw/work.h"

2
src/uvw/async.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "async.h"
#include "async.ipp"

58
src/uvw/async.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef UVW_ASYNC_INCLUDE_H
#define UVW_ASYNC_INCLUDE_H
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
namespace uvw {
/*! @brief Async event. */
struct async_event {};
/**
* @brief The async handle.
*
* Async handles allow the user to _wakeup_ the event loop and get an event
* emitted from another thread.
*
* To create an `async_handle` through a `loop`, no arguments are required.
*/
class async_handle final: public handle<async_handle, uv_async_t, async_event> {
static void send_callback(uv_async_t *hndl);
public:
using handle::handle;
/**
* @brief Initializes the handle.
*
* Unlike other handle initialization functions, it immediately starts the
* handle.
*
* @return Underlying return value.
*/
int init();
/**
* @brief Wakeups the event loop and emits the async event.
*
* Its safe to call this function from any thread.<br/>
* An async event is emitted on the loop thread.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/async.html#c.uv_async_send)
* for further details.
*
* @return Underlying return value.
*/
int send();
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "async.ipp"
#endif
#endif // UVW_ASYNC_INCLUDE_H

View File

@ -1,67 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief AsyncEvent event.
*
* It will be emitted by AsyncHandle according with its functionalities.
*/
struct AsyncEvent {};
/**
* @brief The AsyncHandle handle.
*
* Async handles allow the user to _wakeup_ the event loop and get an event
* emitted from another thread.
*
* To create an `AsyncHandle` through a `Loop`, no arguments are required.
*/
class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
static void sendCallback(uv_async_t *handle) {
AsyncHandle &async = *(static_cast<AsyncHandle*>(handle->data));
async.publish(AsyncEvent{});
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
*
* Unlike other handle initialization functions, it immediately starts the
* handle.
*
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_async_init, &sendCallback);
}
/**
* @brief Wakeups the event loop and emits the AsyncEvent event.
*
* Its safe to call this function from any thread.<br/>
* An AsyncEvent event will be emitted on the loop thread.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/async.html#c.uv_async_send)
* for further details.
*/
void send() {
invoke(&uv_async_send, get());
}
};
}

18
src/uvw/async.ipp Normal file
View File

@ -0,0 +1,18 @@
#include "config.h"
namespace uvw {
UVW_INLINE void async_handle::send_callback(uv_async_t *hndl) {
async_handle &async = *(static_cast<async_handle *>(hndl->data));
async.publish(async_event{});
}
UVW_INLINE int async_handle::init() {
return leak_if(uv_async_init(parent().raw(), raw(), &send_callback));
}
UVW_INLINE int async_handle::send() {
return uv_async_send(raw());
}
} // namespace uvw

2
src/uvw/check.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "check.h"
#include "check.ipp"

56
src/uvw/check.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef UVW_CHECK_INCLUDE_H
#define UVW_CHECK_INCLUDE_H
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
namespace uvw {
/*! @brief Check event. */
struct check_event {};
/**
* @brief The check handle.
*
* Check handles will emit a check event once per loop iteration, right after
* polling for I/O.
*
* To create a `check_handle` through a `loop`, no arguments are required.
*/
class check_handle final: public handle<check_handle, uv_check_t, check_event> {
static void start_callback(uv_check_t *hndl);
public:
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts the handle.
*
* A check event will be emitted once per loop iteration, right after
* polling for I/O.
*
* @return Underlying return value.
*/
int start();
/**
* @brief Stops the handle.
* @return Underlying return value.
*/
int stop();
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "check.ipp"
#endif
#endif // UVW_CHECK_INCLUDE_H

View File

@ -1,66 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief CheckEvent event.
*
* It will be emitted by CheckHandle according with its functionalities.
*
* To create a `CheckHandle` through a `Loop`, no arguments are required.
*/
struct CheckEvent {};
/**
* @brief The CheckHandle handle.
*
* Check handles will emit a CheckEvent event once per loop iteration, right
* after polling for I/O.
*/
class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
static void startCallback(uv_check_t *handle) {
CheckHandle &check = *(static_cast<CheckHandle*>(handle->data));
check.publish(CheckEvent{});
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_check_init);
}
/**
* @brief Starts the handle.
*
* A CheckEvent event will be emitted once per loop iteration, right after
* polling for I/O.
*/
void start() {
invoke(&uv_check_start, get(), &startCallback);
}
/**
* @brief Stops the handle.
*/
void stop() {
invoke(&uv_check_stop, get());
}
};
}

22
src/uvw/check.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void check_handle::start_callback(uv_check_t *hndl) {
check_handle &check = *(static_cast<check_handle *>(hndl->data));
check.publish(check_event{});
}
UVW_INLINE int check_handle::init() {
return leak_if(uv_check_init(parent().raw(), raw()));
}
UVW_INLINE int check_handle::start() {
return uv_check_start(raw(), &start_callback);
}
UVW_INLINE int check_handle::stop() {
return uv_check_stop(raw());
}
} // namespace uvw

10
src/uvw/config.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef UVW_CONFIG_H
#define UVW_CONFIG_H
#ifndef UVW_AS_LIB
# define UVW_INLINE inline
#else
# define UVW_INLINE
#endif
#endif

2
src/uvw/dns.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "dns.h"
#include "dns.ipp"

226
src/uvw/dns.h Normal file
View File

@ -0,0 +1,226 @@
#ifndef UVW_DNS_INCLUDE_H
#define UVW_DNS_INCLUDE_H
#include <memory>
#include <string>
#include <utility>
#include <uv.h>
#include "loop.h"
#include "request.hpp"
#include "util.h"
namespace uvw {
/*! @brief The addrinfo event. */
struct addr_info_event {
using deleter = void (*)(addrinfo *);
addr_info_event(std::unique_ptr<addrinfo, deleter> addr);
/**
* @brief An initialized instance of `addrinfo`.
*
* See [getaddrinfo](http://linux.die.net/man/3/getaddrinfo) for further
* details.
*/
std::unique_ptr<addrinfo, deleter> data;
};
/*! @brief The nameinfo event. */
struct name_info_event {
name_info_event(const char *host, const char *serv);
/**
* @brief A valid hostname.
*
* See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
* details.
*/
const char *hostname;
/**
* @brief A valid service name.
*
* See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
* details.
*/
const char *service;
};
/**
* @brief The getaddrinfo request.
*
* Wrapper for [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `get_addr_info_req` through a `loop`, no arguments are required.
*/
class get_addr_info_req final: public request<get_addr_info_req, uv_getaddrinfo_t, addr_info_event> {
static void addr_info_callback(uv_getaddrinfo_t *req, int status, addrinfo *res);
int node_addr_info(const char *node, const char *service, addrinfo *hints = nullptr);
auto node_addr_info_sync(const char *node, const char *service, addrinfo *hints = nullptr);
public:
using deleter = void (*)(addrinfo *);
using request::request;
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param node Either a numerical network address or a network hostname.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
* @return Underlying return value.
*/
int node_addr_info(const std::string &node, addrinfo *hints = nullptr);
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param node Either a numerical network address or a network hostname.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, deleter>> node_addr_info_sync(const std::string &node, addrinfo *hints = nullptr);
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
* @return Underlying return value.
*/
int service_addr_info(const std::string &service, addrinfo *hints = nullptr);
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, deleter>> service_addr_info_sync(const std::string &service, addrinfo *hints = nullptr);
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param node Either a numerical network address or a network hostname.
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
* @return Underlying return value.
*/
int addr_info(const std::string &node, const std::string &service, addrinfo *hints = nullptr);
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param node Either a numerical network address or a network hostname.
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, deleter>> addr_info_sync(const std::string &node, const std::string &service, addrinfo *hints = nullptr);
};
/**
* @brief The getnameinfo request.
*
* Wrapper for [getnameinfo](http://linux.die.net/man/3/getnameinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `get_name_info_req` through a `loop`, no arguments are required.
*/
class get_name_info_req final: public request<get_name_info_req, uv_getnameinfo_t, name_info_event> {
static void name_info_callback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service);
public:
using request::request;
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
* @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
* @return Underlying return value.
*/
int name_info(const sockaddr &addr, int flags = 0);
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
* @param ip A valid IP address.
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
* @return Underlying return value.
*/
int name_info(const std::string &ip, unsigned int port, int flags = 0);
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
* @param addr A valid instance of socket_address.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
* @return Underlying return value.
*/
int name_info(const socket_address &addr, int flags = 0);
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
*
* @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::pair` composed as it follows:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(const sockaddr &addr, int flags = 0);
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
*
* @param ip A valid IP address.
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::pair` composed as it follows:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(const std::string &ip, unsigned int port, int flags = 0);
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
*
* @param addr A valid instance of socket_address.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::pair` composed as it follows:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(const socket_address &addr, int flags = 0);
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "dns.ipp"
#endif
#endif // UVW_DNS_INCLUDE_H

View File

@ -1,272 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <string>
#include <uv.h>
#include "request.hpp"
#include "util.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief AddrInfoEvent event.
*
* It will be emitted by GetAddrInfoReq according with its functionalities.
*/
struct AddrInfoEvent {
using Deleter = void(*)(addrinfo *);
AddrInfoEvent(std::unique_ptr<addrinfo, Deleter> addr)
: data{std::move(addr)}
{}
/**
* @brief An initialized instance of `addrinfo`.
*
* See [getaddrinfo](http://linux.die.net/man/3/getaddrinfo) for further
* details.
*/
std::unique_ptr<addrinfo, Deleter> data;
};
/**
* @brief NameInfoEvent event.
*
* It will be emitted by GetNameInfoReq according with its functionalities.
*/
struct NameInfoEvent {
NameInfoEvent(const char *host, const char *serv)
: hostname{host}, service{serv}
{}
/**
* @brief A valid hostname.
*
* See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
* details.
*/
const char * hostname;
/**
* @brief A valid service name.
*
* See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
* details.
*/
const char * service;
};
/**
* @brief The GetAddrInfoReq request.
*
* Wrapper for [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `GetAddrInfoReq` through a `Loop`, no arguments are required.
*/
class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
static void addrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
auto ptr = reserve(req);
if(status) {
ptr->publish(ErrorEvent{status});
} else {
auto data = std::unique_ptr<addrinfo, void(*)(addrinfo *)>{
res, [](addrinfo *addr){ uv_freeaddrinfo(addr); }};
ptr->publish(AddrInfoEvent{std::move(data)});
}
}
void nodeAddrInfo(const char *node, const char *service, addrinfo *hints = nullptr) {
invoke(&uv_getaddrinfo, parent(), get(), &addrInfoCallback, node, service, hints);
}
auto nodeAddrInfoSync(const char *node, const char *service, addrinfo *hints = nullptr) {
auto req = get();
auto err = uv_getaddrinfo(parent(), req, nullptr, node, service, hints);
auto data = std::unique_ptr<addrinfo, void(*)(addrinfo *)>{req->addrinfo, [](addrinfo *addr){ uv_freeaddrinfo(addr); }};
return std::make_pair(!err, std::move(data));
}
public:
using Deleter = void(*)(addrinfo *);
using Request::Request;
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param node Either a numerical network address or a network hostname.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*/
void nodeAddrInfo(std::string node, addrinfo *hints = nullptr) {
nodeAddrInfo(node.data(), nullptr, hints);
}
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param node Either a numerical network address or a network hostname.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
nodeAddrInfoSync(std::string node, addrinfo *hints = nullptr) {
return nodeAddrInfoSync(node.data(), nullptr, hints);
}
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*/
void serviceAddrInfo(std::string service, addrinfo *hints = nullptr) {
nodeAddrInfo(nullptr, service.data(), hints);
}
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
serviceAddrInfoSync(std::string service, addrinfo *hints = nullptr) {
return nodeAddrInfoSync(nullptr, service.data(), hints);
}
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
* @param node Either a numerical network address or a network hostname.
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*/
void addrInfo(std::string node, std::string service, addrinfo *hints = nullptr) {
nodeAddrInfo(node.data(), service.data(), hints);
}
/**
* @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
*
* @param node Either a numerical network address or a network hostname.
* @param service Either a service name or a port number as a string.
* @param hints Optional `addrinfo` data structure with additional address
* type constraints.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
*/
std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
addrInfoSync(std::string node, std::string service, addrinfo *hints = nullptr) {
return nodeAddrInfoSync(node.data(), service.data(), hints);
}
};
/**
* @brief The GetNameInfoReq request.
*
* Wrapper for [getnameinfo](http://linux.die.net/man/3/getnameinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `GetNameInfoReq` through a `Loop`, no arguments are required.
*/
class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
static void nameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
auto ptr = reserve(req);
if(status) { ptr->publish(ErrorEvent{status}); }
else { ptr->publish(NameInfoEvent{hostname, service}); }
}
public:
using Request::Request;
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
* @param ip A valid IP address.
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = IPv4>
void nameInfo(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
auto saddr = reinterpret_cast<const sockaddr *>(&addr);
invoke(&uv_getnameinfo, parent(), get(), &nameInfoCallback, saddr, flags);
}
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
* @param addr A valid instance of Addr.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = IPv4>
void nameInfo(Addr addr, int flags = 0) {
nameInfo<I>(addr.ip, addr.port, flags);
}
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
*
* @param ip A valid IP address.
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::pair` composed as it follows:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
template<typename I = IPv4>
std::pair<bool, std::pair<const char *, const char *>>
nameInfoSync(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
auto req = get();
auto saddr = reinterpret_cast<const sockaddr *>(&addr);
auto err = uv_getnameinfo(parent(), req, nullptr, saddr, flags);
return std::make_pair(!err, std::make_pair(req->host, req->service));
}
/**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
*
* @param addr A valid instance of Addr.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * A `std::pair` composed as it follows:
* * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name.
*/
template<typename I = IPv4>
std::pair<bool, std::pair<const char *, const char *>>
nameInfoSync(Addr addr, int flags = 0) {
return nameInfoSync<I>(addr.ip, addr.port, flags);
}
};
}

89
src/uvw/dns.ipp Normal file
View File

@ -0,0 +1,89 @@
#include "config.h"
namespace uvw {
UVW_INLINE addr_info_event::addr_info_event(std::unique_ptr<addrinfo, deleter> addr)
: data{std::move(addr)} {}
UVW_INLINE name_info_event::name_info_event(const char *host, const char *serv)
: hostname{host}, service{serv} {}
UVW_INLINE void get_addr_info_req::addr_info_callback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{res, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
ptr->publish(addr_info_event{std::move(data)});
}
}
UVW_INLINE int get_addr_info_req::node_addr_info(const char *node, const char *service, addrinfo *hints) {
return this->leak_if(uv_getaddrinfo(parent().raw(), raw(), &addr_info_callback, node, service, hints));
}
UVW_INLINE auto get_addr_info_req::node_addr_info_sync(const char *node, const char *service, addrinfo *hints) {
auto req = raw();
auto err = uv_getaddrinfo(parent().raw(), req, nullptr, node, service, hints);
auto data = std::unique_ptr<addrinfo, void (*)(addrinfo *)>{req->addrinfo, [](addrinfo *addr) { uv_freeaddrinfo(addr); }};
return std::make_pair(!err, std::move(data));
}
UVW_INLINE int get_addr_info_req::node_addr_info(const std::string &node, addrinfo *hints) {
return node_addr_info(node.data(), nullptr, hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::node_addr_info_sync(const std::string &node, addrinfo *hints) {
return node_addr_info_sync(node.data(), nullptr, hints);
}
UVW_INLINE int get_addr_info_req::service_addr_info(const std::string &service, addrinfo *hints) {
return node_addr_info(nullptr, service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::service_addr_info_sync(const std::string &service, addrinfo *hints) {
return node_addr_info_sync(nullptr, service.data(), hints);
}
UVW_INLINE int get_addr_info_req::addr_info(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info(node.data(), service.data(), hints);
}
UVW_INLINE std::pair<bool, std::unique_ptr<addrinfo, get_addr_info_req::deleter>> get_addr_info_req::addr_info_sync(const std::string &node, const std::string &service, addrinfo *hints) {
return node_addr_info_sync(node.data(), service.data(), hints);
}
UVW_INLINE void get_name_info_req::name_info_callback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(name_info_event{hostname, service});
}
}
UVW_INLINE int get_name_info_req::name_info(const sockaddr &addr, int flags) {
return this->leak_if(uv_getnameinfo(parent().raw(), raw(), &name_info_callback, &addr, flags));
}
UVW_INLINE int get_name_info_req::name_info(const std::string &ip, unsigned int port, int flags) {
return name_info(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE int get_name_info_req::name_info(const socket_address &addr, int flags) {
return name_info(addr.ip, addr.port, flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const sockaddr &addr, int flags) {
auto req = raw();
auto err = uv_getnameinfo(parent().raw(), req, nullptr, &addr, flags);
return std::make_pair(!err, std::make_pair(req->host, req->service));
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const std::string &ip, unsigned int port, int flags) {
return name_info_sync(details::ip_addr(ip.data(), port), flags);
}
UVW_INLINE std::pair<bool, std::pair<const char *, const char *>> get_name_info_req::name_info_sync(const socket_address &addr, int flags) {
return name_info_sync(addr.ip, addr.port, flags);
}
} // namespace uvw

2
src/uvw/emitter.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "emitter.h"
#include "emitter.ipp"

159
src/uvw/emitter.h Normal file
View File

@ -0,0 +1,159 @@
#ifndef UVW_EMITTER_INCLUDE_H
#define UVW_EMITTER_INCLUDE_H
#include <cstddef>
#include <cstdint>
#include <functional>
#include <list>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <uv.h>
#include "config.h"
#include "type_info.hpp"
namespace uvw {
/**
* @brief Error event.
*
* Custom wrapper around error constants of `libuv`.
*/
struct error_event {
template<typename Type, typename = std::enable_if_t<std::is_integral_v<Type>>>
explicit error_event(Type val) noexcept
: ec{static_cast<int>(val)} {}
/**
* @brief Returns the `libuv` error code equivalent to the given platform dependent error code.
*
* It returns:
* * POSIX error codes on Unix (the ones stored in errno).
* * Win32 error codes on Windows (those returned by GetLastError() or WSAGetLastError()).
*
* If `sys` is already a `libuv` error code, it is simply returned.
*
* @param sys A platform dependent error code.
* @return The `libuv` error code equivalent to the given platform dependent error code.
*/
[[nodiscard]] static int translate(int sys) noexcept;
/**
* @brief Returns the error message for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error message for the given error code.
*/
[[nodiscard]] const char *what() const noexcept;
/**
* @brief Returns the error name for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error name for the given error code.
*/
[[nodiscard]] const char *name() const noexcept;
/**
* @brief Gets the underlying error code, that is an error constant of `libuv`.
* @return The underlying error code.
*/
[[nodiscard]] int code() const noexcept;
/**
* @brief Checks if the event contains a valid error code.
* @return True in case of success, false otherwise.
*/
explicit operator bool() const noexcept;
private:
int ec;
};
/**
* @brief Event emitter base class.
*
* Almost everything in `uvw` is an event emitter.<br/>
* This is the base class from which resources and loops inherit.
*/
template<typename Elem, typename... Event>
class emitter {
public:
template<typename Type>
using listener_t = std::function<void(Type &, Elem &)>;
private:
template<typename Type>
[[nodiscard]] const auto &handler() const noexcept {
return std::get<listener_t<Type>>(handlers);
}
template<typename Type>
[[nodiscard]] auto &handler() noexcept {
return std::get<listener_t<Type>>(handlers);
}
protected:
template<typename Type>
void publish(Type event) {
if(auto &listener = handler<Type>(); listener) {
listener(event, *static_cast<Elem *>(this));
}
}
public:
virtual ~emitter() noexcept {
static_assert(std::is_base_of_v<emitter<Elem, Event...>, Elem>);
}
/**
* @brief Registers a long-lived listener with the event emitter.
*
* This method is used to register a listener with the emitter.<br/>
* A listener is usually defined as a callable object assignable to a
* `std::function<void(const Event &, Elem &)`, where `Event` is the type of
* the event and `Elem` is the type of the resource.
*
* @param f A valid listener to be registered.
*/
template<typename Type>
void on(listener_t<Type> f) {
handler<Type>() = std::move(f);
}
/*! @brief Disconnects the listener for the given event type. */
template<typename Type>
void reset() noexcept {
handler<Type>() = nullptr;
}
/*! @brief Disconnects all listeners. */
void reset() noexcept {
reset<error_event>();
(reset<Event>(), ...);
}
/**
* @brief Checks if there is a listener registered for the specific event.
* @return True if there is a listener registered for the specific event,
* false otherwise.
*/
template<typename Type>
[[nodiscard]] bool has() const noexcept {
return static_cast<bool>(handler<Type>());
}
private:
std::tuple<listener_t<error_event>, listener_t<Event>...> handlers{};
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "emitter.ipp"
#endif
#endif // UVW_EMITTER_INCLUDE_H

View File

@ -1,318 +0,0 @@
#pragma once
#include <type_traits>
#include <functional>
#include <algorithm>
#include <utility>
#include <cstddef>
#include <vector>
#include <memory>
#include <list>
#include <uv.h>
namespace uvw {
/**
* @brief The ErrorEvent event.
*
* Custom wrapper around error constants of `libuv`.
*/
struct ErrorEvent {
template<typename U, typename = std::enable_if_t<std::is_integral<U>::value>>
explicit ErrorEvent(U val) noexcept
: ec{static_cast<int>(val)}
{}
/**
* @brief Returns the `libuv` error code equivalent to the given platform dependent error code.
*
* It returns:
* * POSIX error codes on Unix (the ones stored in errno).
* * Win32 error codes on Windows (those returned by GetLastError() or WSAGetLastError()).
*
* If `sys` is already a `libuv` error code, it is simply returned.
*
* @param sys A platform dependent error code.
* @return The `libuv` error code equivalent to the given platform dependent error code.
*/
static int translate(int sys) noexcept {
return uv_translate_sys_error(sys);
}
/**
* @brief Returns the error message for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error message for the given error code.
*/
const char * what() const noexcept { return uv_strerror(ec); }
/**
* @brief Returns the error name for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error name for the given error code.
*/
const char * name() const noexcept { return uv_err_name(ec); }
/**
* @brief Gets the underlying error code, that is an error constant of `libuv`.
* @return The underlying error code.
*/
int code() const noexcept { return ec; }
/**
* @brief Checks if the event contains a valid error code.
* @return True in case of success, false otherwise.
*/
explicit operator bool() const noexcept { return ec < 0; }
private:
const int ec;
};
/**
* @brief Event emitter base class.
*
* Almost everything in `uvw` is an event emitter.<br/>
* This is the base class from which resources and loops inherit.
*/
template<typename T>
class Emitter {
struct BaseHandler {
virtual ~BaseHandler() noexcept = default;
virtual bool empty() const noexcept = 0;
virtual void clear() noexcept = 0;
};
template<typename E>
struct Handler final: BaseHandler {
using Listener = std::function<void(E &, T &)>;
using Element = std::pair<bool, Listener>;
using ListenerList = std::list<Element>;
using Connection = typename ListenerList::iterator;
bool empty() const noexcept override {
auto pred = [](auto &&element){ return element.first; };
return std::all_of(onceL.cbegin(), onceL.cend(), pred) &&
std::all_of(onL.cbegin(), onL.cend(), pred);
}
void clear() noexcept override {
if(publishing) {
auto func = [](auto &&element){ element.first = true; };
std::for_each(onceL.begin(), onceL.end(), func);
std::for_each(onL.begin(), onL.end(), func);
} else {
onceL.clear();
onL.clear();
}
}
Connection once(Listener f) {
return onceL.emplace(onceL.cend(), false, std::move(f));
}
Connection on(Listener f) {
return onL.emplace(onL.cend(), false, std::move(f));
}
void erase(Connection conn) noexcept {
conn->first = true;
if(!publishing) {
auto pred = [](auto &&element){ return element.first; };
onceL.remove_if(pred);
onL.remove_if(pred);
}
}
void publish(E event, T &ref) {
ListenerList currentL;
onceL.swap(currentL);
auto func = [&event, &ref](auto &&element) {
return element.first ? void() : element.second(event, ref);
};
publishing = true;
std::for_each(onL.rbegin(), onL.rend(), func);
std::for_each(currentL.rbegin(), currentL.rend(), func);
publishing = false;
onL.remove_if([](auto &&element){ return element.first; });
}
private:
bool publishing{false};
ListenerList onceL{};
ListenerList onL{};
};
static std::size_t next_type() noexcept {
static std::size_t counter = 0;
return counter++;
}
template<typename>
static std::size_t event_type() noexcept {
static std::size_t value = next_type();
return value;
}
template<typename E>
Handler<E> & handler() noexcept {
std::size_t type = event_type<E>();
if(!(type < handlers.size())) {
handlers.resize(type+1);
}
if(!handlers[type]) {
handlers[type] = std::make_unique<Handler<E>>();
}
return static_cast<Handler<E>&>(*handlers[type]);
}
protected:
template<typename E>
void publish(E event) {
handler<E>().publish(std::move(event), *static_cast<T*>(this));
}
public:
template<typename E>
using Listener = typename Handler<E>::Listener;
/**
* @brief Connection type for a given event type.
*
* Given an event type `E`, `Connection<E>` is the type of the connection
* object returned by the event emitter whenever a listener for the given
* type is registered.
*/
template<typename E>
struct Connection: private Handler<E>::Connection {
template<typename> friend class Emitter;
Connection() = default;
Connection(const Connection &) = default;
Connection(Connection &&) = default;
Connection(typename Handler<E>::Connection conn)
: Handler<E>::Connection{std::move(conn)}
{}
Connection & operator=(const Connection &) = default;
Connection & operator=(Connection &&) = default;
};
virtual ~Emitter() noexcept {
static_assert(std::is_base_of<Emitter<T>, T>::value, "!");
}
/**
* @brief Registers a long-lived listener with the event emitter.
*
* This method can be used to register a listener that is meant to be
* invoked more than once for the given event type.<br/>
* The Connection object returned by the method can be freely discarded. It
* can be used later to disconnect the listener, if needed.
*
* Listener is usually defined as a callable object assignable to a
* `std::function<void(const E &, T &)`, where `E` is the type of the event
* and `T` is the type of the resource.
*
* @param f A valid listener to be registered.
* @return Connection object to be used later to disconnect the listener.
*/
template<typename E>
Connection<E> on(Listener<E> f) {
return handler<E>().on(std::move(f));
}
/**
* @brief Registers a short-lived listener with the event emitter.
*
* This method can be used to register a listener that is meant to be
* invoked only once for the given event type.<br/>
* The Connection object returned by the method can be freely discarded. It
* can be used later to disconnect the listener, if needed.
*
* Listener is usually defined as a callable object assignable to a
* `std::function<void(const E &, T &)`, where `E` is the type of the event
* and `T` is the type of the resource.
*
* @param f Avalid listener to be registered.
* @return Connection object to be used later to disconnect the listener.
*/
template<typename E>
Connection<E> once(Listener<E> f) {
return handler<E>().once(std::move(f));
}
/**
* @brief Disconnects a listener from the event emitter.
* @param conn A valid Connection object
*/
template<typename E>
void erase(Connection<E> conn) noexcept {
handler<E>().erase(std::move(conn));
}
/**
* @brief Disconnects all the listeners for the given event type.
*/
template<typename E>
void clear() noexcept {
handler<E>().clear();
}
/**
* @brief Disconnects all the listeners.
*/
void clear() noexcept {
std::for_each(handlers.begin(), handlers.end(),
[](auto &&hdlr){ if(hdlr) { hdlr->clear(); } });
}
/**
* @brief Checks if there are listeners registered for the specific event.
* @return True if there are no listeners registered for the specific event,
* false otherwise.
*/
template<typename E>
bool empty() const noexcept {
std::size_t type = event_type<E>();
return (!(type < handlers.size()) ||
!handlers[type] ||
static_cast<Handler<E>&>(*handlers[type]).empty());
}
/**
* @brief Checks if there are listeners registered with the event emitter.
* @return True if there are no listeners registered with the event emitter,
* false otherwise.
*/
bool empty() const noexcept {
return std::all_of(handlers.cbegin(), handlers.cend(),
[](auto &&hdlr){ return !hdlr || hdlr->empty(); });
}
private:
std::vector<std::unique_ptr<BaseHandler>> handlers{};
};
}

25
src/uvw/emitter.ipp Normal file
View File

@ -0,0 +1,25 @@
#include "config.h"
namespace uvw {
UVW_INLINE int error_event::translate(int sys) noexcept {
return uv_translate_sys_error(sys);
}
UVW_INLINE const char *error_event::what() const noexcept {
return uv_strerror(ec);
}
UVW_INLINE const char *error_event::name() const noexcept {
return uv_err_name(ec);
}
UVW_INLINE int error_event::code() const noexcept {
return ec;
}
UVW_INLINE error_event::operator bool() const noexcept {
return ec < 0;
}
} // namespace uvw

76
src/uvw/enum.hpp Normal file
View File

@ -0,0 +1,76 @@
#ifndef UVW_ENUM_INCLUDE_HPP
#define UVW_ENUM_INCLUDE_HPP
#include <type_traits>
#include "config.h"
/**
* @brief Operator available for enums for which bitmask support is enabled.
* @tparam Type Enum class type.
* @param lhs The first value to use.
* @param rhs The second value to use.
* @return The result of invoking the operator on the underlying types of the
* two values provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator|(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator&(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator^(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
}
/**
* @brief Operator available for enums for which bitmask support is enabled.
* @tparam Type Enum class type.
* @param value The value to use.
* @return The result of invoking the operator on the underlying types of the
* value provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator~(const Type value) noexcept {
return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
}
/*! @copydoc operator~ */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM, bool{})>
operator!(const Type value) noexcept {
return !static_cast<std::underlying_type_t<Type>>(value);
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator|=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs | rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator&=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs & rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator^=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs ^ rhs));
}
#endif

2
src/uvw/fs.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "fs.h"
#include "fs.ipp"

1235
src/uvw/fs.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

550
src/uvw/fs.ipp Normal file
View File

@ -0,0 +1,550 @@
#include <array>
#include "config.h"
namespace uvw {
UVW_INLINE void file_req::fs_open_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = static_cast<uv_file>(req->result);
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_close_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->file = BAD_FD;
ptr->publish(fs_event{*req});
}
}
UVW_INLINE void file_req::fs_read_callback(uv_fs_t *req) {
if(auto ptr = reserve(req); req->result < 0) {
ptr->publish(error_event{req->result});
} else {
ptr->publish(fs_event{*req, std::move(ptr->current)});
}
}
UVW_INLINE file_req::~file_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void file_req::close() {
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), raw(), file, &fs_close_callback);
}
UVW_INLINE bool file_req::close_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_close(parent().raw(), req, file, nullptr);
if(req->result >= 0) {
file = BAD_FD;
}
return !(req->result < 0);
}
UVW_INLINE void file_req::open(const std::string &path, file_open_flags flags, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), raw(), path.data(), static_cast<int>(flags), mode, &fs_open_callback);
}
UVW_INLINE bool file_req::open_sync(const std::string &path, file_open_flags flags, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_open(parent().raw(), req, path.data(), static_cast<int>(flags), mode, nullptr);
if(req->result >= 0) {
file = static_cast<uv_file>(req->result);
}
return !(req->result < 0);
}
UVW_INLINE void file_req::read(int64_t offset, unsigned int len) {
current = std::make_unique<char[]>(len);
buffer = uv_buf_init(current.get(), len);
std::array bufs{buffer};
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_read_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::unique_ptr<const char[]>, std::size_t>> file_req::read_sync(int64_t offset, unsigned int len) {
current = std::make_unique<char[]>(len);
buffer = uv_buf_init(current.get(), len);
std::array bufs{buffer};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), req, file, bufs.data(), 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(std::move(current), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void file_req::write(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
std::array bufs{uv_buf_init(current.get(), len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_request_callback);
}
UVW_INLINE void file_req::write(char *buf, unsigned int len, int64_t offset) {
std::array bufs{uv_buf_init(buf, len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs.data(), 1, offset, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::write_sync(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset) {
current = std::move(buf);
std::array bufs{uv_buf_init(current.get(), len)};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), req, file, bufs.data(), 1, offset, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::stat() {
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> file_req::stat_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fstat(parent().raw(), req, file, nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void file_req::sync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::sync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fsync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::datasync() {
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), raw(), file, &fs_request_callback);
}
UVW_INLINE bool file_req::datasync_sync() {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fdatasync(parent().raw(), req, file, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::truncate(int64_t offset) {
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), raw(), file, offset, &fs_request_callback);
}
UVW_INLINE bool file_req::truncate_sync(int64_t offset) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_ftruncate(parent().raw(), req, file, offset, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::sendfile(file_handle out, int64_t offset, std::size_t length) {
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), raw(), out, file, offset, length, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> file_req::sendfile_sync(file_handle out, int64_t offset, std::size_t length) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_sendfile(parent().raw(), req, out, file, offset, length, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE void file_req::chmod(int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), raw(), file, mode, &fs_request_callback);
}
UVW_INLINE bool file_req::chmod_sync(int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchmod(parent().raw(), req, file, mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::futime(fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), raw(), file, atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool file_req::futime_sync(fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_futime(parent().raw(), req, file, atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void file_req::chown(uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), raw(), file, uid, gid, &fs_request_callback);
}
UVW_INLINE bool file_req::chown_sync(uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_fchown(parent().raw(), req, file, uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE file_req::operator file_handle() const noexcept {
return file;
}
UVW_INLINE fs_req::~fs_req() noexcept {
uv_fs_req_cleanup(raw());
}
UVW_INLINE void fs_req::unlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::unlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_unlink(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdir(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::mkdir_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdir(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::mkdtemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::mkdtemp_sync(const std::string &tpl) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkdtemp(parent().raw(), req, tpl.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::mkstemp(const std::string &tpl) {
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), raw(), tpl.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<std::string, std::size_t>> fs_req::mkstemp_sync(const std::string &tpl) {
std::pair<bool, std::pair<std::string, std::size_t>> ret{false, {}};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_mkstemp(parent().raw(), req, tpl.data(), nullptr);
ret.first = !(req->result < 0);
if(ret.first) {
ret.second.first = req->path;
ret.second.second = static_cast<std::size_t>(req->result);
}
return ret;
}
UVW_INLINE void fs_req::lutime(const std::string &path, time atime, time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::lutime_sync(const std::string &path, time atime, time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lutime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::rmdir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rmdir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rmdir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::scandir(const std::string &path, int flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), raw(), path.data(), flags, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::size_t> fs_req::scandir_sync(const std::string &path, int flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_scandir(parent().raw(), req, path.data(), flags, nullptr);
bool err = req->result < 0;
return std::make_pair(!err, err ? 0 : std::size_t(req->result));
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::scandir_next() {
std::pair<bool, std::pair<entry_type, const char *>> ret{false, {entry_type::UNKNOWN, nullptr}};
uv_fs_req_cleanup(raw());
auto res = uv_fs_scandir_next(raw(), &dirents);
if(UV_EOF != res) {
ret.second.first = static_cast<entry_type>(dirents.type);
ret.second.second = dirents.name;
ret.first = true;
}
return ret;
}
UVW_INLINE void fs_req::stat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::stat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_stat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::lstat(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, file_info> fs_req::lstat_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lstat(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->statbuf);
}
UVW_INLINE void fs_req::statfs(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, fs_info> fs_req::statfs_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_statfs(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), *static_cast<uv_statfs_t *>(req->ptr));
}
UVW_INLINE void fs_req::rename(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::rename_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_rename(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::copyfile(const std::string &old, const std::string &path, copy_file_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_copyfile(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::access(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::access_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_access(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::chmod(const std::string &path, int mode) {
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), raw(), path.data(), mode, &fs_request_callback);
}
UVW_INLINE bool fs_req::chmod_sync(const std::string &path, int mode) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chmod(parent().raw(), req, path.data(), mode, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::utime(const std::string &path, fs_request::time atime, fs_request::time mtime) {
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), raw(), path.data(), atime.count(), mtime.count(), &fs_request_callback);
}
UVW_INLINE bool fs_req::utime_sync(const std::string &path, fs_request::time atime, fs_request::time mtime) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_utime(parent().raw(), req, path.data(), atime.count(), mtime.count(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::link(const std::string &old, const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), raw(), old.data(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::link_sync(const std::string &old, const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_link(parent().raw(), req, old.data(), path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::symlink(const std::string &old, const std::string &path, symlink_flags flags) {
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), raw(), old.data(), path.data(), static_cast<int>(flags), &fs_request_callback);
}
UVW_INLINE bool fs_req::symlink_sync(const std::string &old, const std::string &path, symlink_flags flags) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_symlink(parent().raw(), req, old.data(), path.data(), static_cast<int>(flags), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readlink(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<const char *, std::size_t>> fs_req::readlink_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_readlink(parent().raw(), req, path.data(), nullptr);
bool err = req->result < 0;
return std::make_pair(!err, std::make_pair(static_cast<char *>(req->ptr), err ? 0 : std::size_t(req->result)));
}
UVW_INLINE void fs_req::realpath(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE std::pair<bool, const char *> fs_req::realpath_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_realpath(parent().raw(), req, path.data(), nullptr);
return std::make_pair(!(req->result < 0), req->path);
}
UVW_INLINE void fs_req::chown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::chown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_chown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::lchown(const std::string &path, uid_type uid, gid_type gid) {
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), raw(), path.data(), uid, gid, &fs_request_callback);
}
UVW_INLINE bool fs_req::lchown_sync(const std::string &path, uid_type uid, gid_type gid) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_lchown(parent().raw(), req, path.data(), uid, gid, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::opendir(const std::string &path) {
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), raw(), path.data(), &fs_request_callback);
}
UVW_INLINE bool fs_req::opendir_sync(const std::string &path) {
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_opendir(parent().raw(), req, path.data(), nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::closedir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE bool fs_req::closedir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
uv_fs_req_cleanup(this->raw());
uv_fs_closedir(parent().raw(), req, dir, nullptr);
return !(req->result < 0);
}
UVW_INLINE void fs_req::readdir() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = &dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, &fs_request_callback);
}
UVW_INLINE std::pair<bool, std::pair<fs_req::entry_type, const char *>> fs_req::readdir_sync() {
auto req = raw();
auto *dir = static_cast<uv_dir_t *>(req->ptr);
dir->dirents = &dirents;
dir->nentries = 1;
uv_fs_req_cleanup(this->raw());
uv_fs_readdir(parent().raw(), req, dir, nullptr);
return {req->result != 0, {static_cast<entry_type>(dirents.type), dirents.name}};
}
UVW_INLINE os_file_descriptor fs_helper::handle(file_handle file) noexcept {
return uv_get_osfhandle(file);
}
UVW_INLINE file_handle fs_helper::open(os_file_descriptor descriptor) noexcept {
return uv_open_osfhandle(descriptor);
}
} // namespace uvw

2
src/uvw/fs_event.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "fs_event.h"
#include "fs_event.ipp"

120
src/uvw/fs_event.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef UVW_FS_EVENT_INCLUDE_H
#define UVW_FS_EVENT_INCLUDE_H
#include <string>
#include <type_traits>
#include <uv.h>
#include "config.h"
#include "enum.hpp"
#include "handle.hpp"
#include "loop.h"
#include "util.h"
namespace uvw {
namespace details {
enum class uvw_fs_event_flags : std::underlying_type_t<uv_fs_event_flags> {
WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY,
STAT = UV_FS_EVENT_STAT,
RECURSIVE = UV_FS_EVENT_RECURSIVE,
UVW_ENUM = 0
};
enum class uvw_fs_event : std::underlying_type_t<uv_fs_event> {
RENAME = UV_RENAME,
CHANGE = UV_CHANGE
};
} // namespace details
/*! @brief Fs event event. */
struct fs_event_event {
fs_event_event(const char *pathname, details::uvw_fs_event events);
/**
* @brief The path to the file being monitored.
*
* If the handle was started with a directory, the filename parameter will
* be a relative path to a file contained in the directory.
*/
const char *filename;
/**
* @brief Detected events all in one.
*
* Available flags are:
*
* * `fs_event_handle::watch::RENAME`
* * `fs_event_handle::watch::CHANGE`
*/
details::uvw_fs_event flags;
};
/**
* @brief The fs event handle.
*
* These handles allow the user to monitor a given path for changes, for
* example, if the file was renamed or there was a generic change in it. The
* best backend for the job on each platform is chosen by the handle.
*
* To create a `fs_event_handle` through a `loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/fs_event.html)
* for further details.
*/
class fs_event_handle final: public handle<fs_event_handle, uv_fs_event_t, fs_event_event> {
static void start_callback(uv_fs_event_t *hndl, const char *filename, int events, int status);
public:
using watch = details::uvw_fs_event;
using event_flags = details::uvw_fs_event_flags;
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts watching the specified path.
*
* It will watch the specified path for changes.<br/>
* As soon as a change is observed, a fs_event_event is emitted by the
* handle.
*
* Available flags are:
*
* * `fs_event_handle::event_flags::WATCH_ENTRY`
* * `fs_event_handle::event_flags::STAT`
* * `fs_event_handle::event_flags::RECURSIVE`
*
* @param path The file or directory to be monitored.
* @param flags Additional flags to control the behavior.
* @return Underlying return value.
*/
int start(const std::string &path, event_flags flags = event_flags::UVW_ENUM);
/**
* @brief Stops polling the file descriptor.
* @return Underlying return value.
*/
int stop();
/**
* @brief Gets the path being monitored.
* @return The path being monitored, an empty string in case of errors.
*/
std::string path() noexcept;
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "fs_event.ipp"
#endif
#endif // UVW_FS_EVENT_INCLUDE_H

View File

@ -1,158 +0,0 @@
#pragma once
#include <utility>
#include <string>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "util.hpp"
#include "loop.hpp"
namespace uvw {
namespace details {
enum class UVFsEventFlags: std::underlying_type_t<uv_fs_event_flags> {
WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY,
STAT = UV_FS_EVENT_STAT,
RECURSIVE = UV_FS_EVENT_RECURSIVE
};
enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
RENAME = UV_RENAME,
CHANGE = UV_CHANGE
};
}
/**
* @brief FsEventEvent event.
*
* It will be emitted by FsEventHandle according with its functionalities.
*/
struct FsEventEvent {
FsEventEvent(const char * pathname, Flags<details::UVFsEvent> events)
: filename{pathname}, flags{std::move(events)}
{}
/**
* @brief The path to the file being monitored.
*
* If the handle was started with a directory, the filename parameter will
* be a relative path to a file contained in the directory.
*/
const char * filename;
/**
* @brief Detected events all in one.
*
* Available flags are:
*
* * `FsEventHandle::Watch::RENAME`
* * `FsEventHandle::Watch::CHANGE`
*/
Flags<details::UVFsEvent> flags;
};
/**
* @brief The FsEventHandle handle.
*
* These handles allow the user to monitor a given path for changes, for
* example, if the file was renamed or there was a generic change in it. The
* best backend for the job on each platform is chosen by the handle.
*
* To create a `FsEventHandle` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/fs_event.html)
* for further details.
*/
class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
static void startCallback(uv_fs_event_t *handle, const char *filename, int events, int status) {
FsEventHandle &fsEvent = *(static_cast<FsEventHandle*>(handle->data));
if(status) { fsEvent.publish(ErrorEvent{status}); }
else { fsEvent.publish(FsEventEvent{filename, static_cast<std::underlying_type_t<Event>>(events)}); }
}
public:
using Watch = details::UVFsEvent;
using Event = details::UVFsEventFlags;
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_fs_event_init);
}
/**
* @brief Starts watching the specified path.
*
* It will watch the specified path for changes.<br/>
* As soon as a change is observed, a FsEventEvent is emitted by the
* handle.<br>
* It could happen that ErrorEvent events are emitted while running.
*
* Available flags are:
*
* * `FsEventHandle::Event::WATCH_ENTRY`
* * `FsEventHandle::Event::STAT`
* * `FsEventHandle::Event::RECURSIVE`
*
* @param path The file or directory to be monitored.
* @param flags Additional flags to control the behavior.
*/
void start(std::string path, Flags<Watch> flags = Flags<Watch>{}) {
invoke(&uv_fs_event_start, get(), &startCallback, path.data(), flags);
}
/**
* @brief Starts watching the specified path.
*
* It will watch the specified path for changes.<br/>
* As soon as a change is observed, a FsEventEvent is emitted by the
* handle.<br>
* It could happen that ErrorEvent events are emitted while running.
*
* Available flags are:
*
* * `FsEventHandle::Event::WATCH_ENTRY`
* * `FsEventHandle::Event::STAT`
* * `FsEventHandle::Event::RECURSIVE`
*
* @param path The file or directory to be monitored.
* @param watch Additional flag to control the behavior.
*/
void start(std::string path, Watch watch) {
start(std::move(path), Flags<Watch>{watch});
}
/**
* @brief Stops polling the file descriptor.
*/
void stop() {
invoke(&uv_fs_event_stop, get());
}
/**
* @brief Gets the path being monitored.
* @return The path being monitored, an empty string in case of errors.
*/
std::string path() noexcept {
return details::tryRead(&uv_fs_event_getpath, get());
}
};
}

33
src/uvw/fs_event.ipp Normal file
View File

@ -0,0 +1,33 @@
#include "config.h"
namespace uvw {
UVW_INLINE fs_event_event::fs_event_event(const char *pathname, details::uvw_fs_event events)
: filename{pathname}, flags{events} {}
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
UVW_INLINE void fs_event_handle::start_callback(uv_fs_event_t *hndl, const char *filename, int events, int status) {
if(fs_event_handle &fsEvent = *(static_cast<fs_event_handle *>(hndl->data)); status) {
fsEvent.publish(error_event{status});
} else {
fsEvent.publish(fs_event_event{filename, details::uvw_fs_event(events)});
}
}
UVW_INLINE int fs_event_handle::init() {
return leak_if(uv_fs_event_init(parent().raw(), raw()));
}
UVW_INLINE int fs_event_handle::start(const std::string &path, event_flags flags) {
return uv_fs_event_start(raw(), &start_callback, path.data(), static_cast<uv_fs_event_flags>(flags));
}
UVW_INLINE int fs_event_handle::stop() {
return uv_fs_event_stop(raw());
}
UVW_INLINE std::string fs_event_handle::path() noexcept {
return details::try_read(&uv_fs_event_getpath, raw());
}
} // namespace uvw

2
src/uvw/fs_poll.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "fs_poll.h"
#include "fs_poll.ipp"

76
src/uvw/fs_poll.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef UVW_FS_POLL_INCLUDE_H
#define UVW_FS_POLL_INCLUDE_H
#include <chrono>
#include <string>
#include <uv.h>
#include "config.h"
#include "handle.hpp"
#include "loop.h"
#include "util.h"
namespace uvw {
/*! @brief Fs pos event. */
struct fs_poll_event {
explicit fs_poll_event(file_info previous, file_info current) noexcept;
file_info prev; /*!< The old file_info struct. */
file_info curr; /*!< The new file_info struct. */
};
/**
* @brief The fs poll handle.
*
* It allows users to monitor a given path for changes. Unlike fs_event_handle,
* fs_poll_handle uses stat to detect when a file has changed so it can work on
* file systems where fs_event_handle handles cant.
*
* To create a `fs_poll_handle` through a `loop`, no arguments are required.
*/
class fs_poll_handle final: public handle<fs_poll_handle, uv_fs_poll_t, fs_poll_event> {
static void start_callback(uv_fs_poll_t *hndl, int status, const uv_stat_t *prev, const uv_stat_t *curr);
public:
using time = std::chrono::duration<unsigned int, std::milli>;
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts the handle.
*
* The handle will start emitting fs_poll_event when needed.
*
* @param file The path to the file to be checked.
* @param interval Milliseconds between successive checks.
* @return Underlying return value.
*/
int start(const std::string &file, time interval);
/**
* @brief Stops the handle.
* @return Underlying return value.
*/
int stop();
/**
* @brief Gets the path being monitored by the handle.
* @return The path being monitored by the handle, an empty string in case
* of errors.
*/
std::string path() noexcept;
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "fs_poll.ipp"
#endif
#endif // UVW_FS_POLL_INCLUDE_H

View File

@ -1,88 +0,0 @@
#pragma once
#include <utility>
#include <string>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "util.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief FsPollEvent event.
*
* It will be emitted by FsPollHandle according with its functionalities.
*/
struct FsPollEvent {
explicit FsPollEvent(Stat previous, Stat current) noexcept
: prev{std::move(previous)}, curr{std::move(current)}
{}
Stat prev; /*!< The old Stat struct. */
Stat curr; /*!< The new Stat struct. */
};
/**
* @brief The FsPollHandle handle.
*
* It allows the user to monitor a given path for changes. Unlike FsEventHandle
* handles, FsPollHandle handles use stat to detect when a file has changed so
* they can work on file systems where FsEventHandle handles cant.
*
* To create a `FsPollHandle` through a `Loop`, no arguments are required.
*/
class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
FsPollHandle &fsPoll = *(static_cast<FsPollHandle*>(handle->data));
if(status) { fsPoll.publish(ErrorEvent{status}); }
else { fsPoll.publish(FsPollEvent{ *prev, *curr }); }
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_fs_poll_init);
}
/**
* @brief Starts the handle.
*
* The handle will start emitting FsPollEvent when needed.
*
* @param file The path to the file to be checked.
* @param interval Milliseconds between successive checks.
*/
void start(std::string file, unsigned int interval) {
invoke(&uv_fs_poll_start, get(), &startCallback, file.data(), interval);
}
/**
* @brief Stops the handle.
*/
void stop() {
invoke(&uv_fs_poll_stop, get());
}
/**
* @brief Gets the path being monitored by the handle.
* @return The path being monitored by the handle, an empty string in case
* of errors.
*/
std::string path() noexcept {
return details::tryRead(&uv_fs_poll_getpath, get());
}
};
}

32
src/uvw/fs_poll.ipp Normal file
View File

@ -0,0 +1,32 @@
#include "config.h"
namespace uvw {
UVW_INLINE fs_poll_event::fs_poll_event(file_info previous, file_info current) noexcept
: prev{previous}, curr{current} {}
UVW_INLINE void fs_poll_handle::start_callback(uv_fs_poll_t *hndl, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
if(fs_poll_handle &fsPoll = *(static_cast<fs_poll_handle *>(hndl->data)); status) {
fsPoll.publish(error_event{status});
} else {
fsPoll.publish(fs_poll_event{*prev, *curr});
}
}
UVW_INLINE int fs_poll_handle::init() {
return leak_if(uv_fs_poll_init(parent().raw(), raw()));
}
UVW_INLINE int fs_poll_handle::start(const std::string &file, fs_poll_handle::time interval) {
return uv_fs_poll_start(raw(), &start_callback, file.data(), interval.count());
}
UVW_INLINE int fs_poll_handle::stop() {
return uv_fs_poll_stop(raw());
}
UVW_INLINE std::string fs_poll_handle::path() noexcept {
return details::try_read(&uv_fs_poll_getpath, raw());
}
} // namespace uvw

View File

@ -1,93 +1,92 @@
#pragma once
#ifndef UVW_HANDLE_INCLUDE_H
#define UVW_HANDLE_INCLUDE_H
#include <cstddef>
#include <utility>
#include <memory>
#include <utility>
#include <uv.h>
#include "config.h"
#include "resource.hpp"
#include "util.hpp"
#include "util.h"
namespace uvw {
/**
* @brief CloseEvent event.
*
* It will be emitted by the handles according with their functionalities.
*/
struct CloseEvent {};
/*! @brief Close event. */
struct close_event {};
/**
* @brief Handle base class.
*
* Base type for all `uvw` handle types.
*/
template<typename T, typename U>
class Handle: public BaseHandle, public Resource<T, U>
{
static void closeCallback(uv_handle_t *handle) {
Handle<T, U> &ref = *(static_cast<T*>(handle->data));
auto ptr = ref.shared_from_this();
(void)ptr;
ref.reset();
ref.publish(CloseEvent{});
}
template<typename T, typename U, typename... E>
class handle: public resource<T, U, close_event, E...> {
protected:
static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
auto size = static_cast<unsigned int>(suggested);
*buf = uv_buf_init(new char[size], size);
static void close_callback(uv_handle_t *hndl) {
handle<T, U, E...> &ref = *(static_cast<T *>(hndl->data));
[[maybe_unused]] auto ptr = ref.shared_from_this();
ref.self_reset();
ref.publish(close_event{});
}
template<typename F, typename... Args>
bool initialize(F &&f, Args&&... args) {
if(!this->self()) {
auto err = std::forward<F>(f)(this->parent(), this->get(), std::forward<Args>(args)...);
if(err) {
this->publish(ErrorEvent{err});
} else {
this->leak();
}
}
return this->self();
[[nodiscard]] uv_handle_t *as_uv_handle() {
return reinterpret_cast<uv_handle_t *>(this->raw());
}
template<typename F, typename... Args>
auto invoke(F &&f, Args&&... args) {
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
return err;
[[nodiscard]] const uv_handle_t *as_uv_handle() const {
return reinterpret_cast<const uv_handle_t *>(this->raw());
}
public:
using Resource<T, U>::Resource;
using resource<T, U, close_event, E...>::resource;
/**
* @brief Gets the category of the handle.
*
* A base handle offers no functionality to promote it to the actual handle
* type. By means of this function, an opaque value that identifies the
* category of the handle is made available to the users.
*
* @return The actual category of the handle.
*/
[[nodiscard]] handle_category category() const noexcept {
return handle_category{as_uv_handle()->type};
}
/**
* @brief Gets the type of the handle.
*
* A base handle offers no functionality to promote it to the actual handle
* type. By means of this function, the type of the underlying handle as
* specified by handle_type is made available to the users.
*
* @return The actual type of the handle.
*/
[[nodiscard]] handle_type type() const noexcept {
return utilities::guess_handle(category());
}
/**
* @brief Checks if the handle is active.
*
* What _active_ means depends on the type of handle:
*
* * An AsyncHandle handle is always active and cannot be deactivated,
* * An async_handle handle is always active and cannot be deactivated,
* except by closing it with uv_close().
* * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
* that deals with I/O - is active when it is doing something that involves
* I/O, like reading, writing, connecting, accepting new connections, etc.
* * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
* has been started with a call to `start()`.
* * A pipe, tcp, udp, etc. handle - basically any handle that deals with
* I/O - is active when it is doing something that involves I/O, like
* reading, writing, connecting, accepting new connections, etc.
* * A check, idle, timer, etc. handle is active when it has been started
* with a call to `start()`.
*
* Rule of thumb: if a handle of type `FooHandle` has a `start()` member
* Rule of thumb: if a handle of type `foo_handle` has a `start()` member
* method, then its active from the moment that method is called. Likewise,
* `stop()` deactivates the handle again.
*
* @return True if the handle is active, false otherwise.
*/
bool active() const noexcept override {
return !(uv_is_active(this->template get<uv_handle_t>()) == 0);
[[nodiscard]] bool active() const noexcept {
return !!uv_is_active(as_uv_handle());
}
/**
@ -98,22 +97,21 @@ public:
*
* @return True if the handle is closing or closed, false otherwise.
*/
bool closing() const noexcept override {
return !(uv_is_closing(this->template get<uv_handle_t>()) == 0);
[[nodiscard]] bool closing() const noexcept {
return !!uv_is_closing(as_uv_handle());
}
/**
* @brief Request handle to be closed.
*
* This **must** be called on each handle before memory is released.<br/>
* In-progress requests are cancelled and this can result in an ErrorEvent
* emitted.
* In-progress requests are cancelled and this can result in errors.
*
* The handle will emit a CloseEvent when finished.
* The handle will emit a close event when finished.
*/
void close() noexcept override {
void close() noexcept {
if(!closing()) {
uv_close(this->template get<uv_handle_t>(), &Handle<T, U>::closeCallback);
uv_close(as_uv_handle(), &handle<T, U, E...>::close_callback);
}
}
@ -123,8 +121,8 @@ public:
* References are idempotent, that is, if a handle is already referenced
* calling this function again will have no effect.
*/
void reference() noexcept override {
uv_ref(this->template get<uv_handle_t>());
void reference() noexcept {
uv_ref(as_uv_handle());
}
/**
@ -133,24 +131,24 @@ public:
* References are idempotent, that is, if a handle is not referenced calling
* this function again will have no effect.
*/
void unreference() noexcept override {
uv_unref(this->template get<uv_handle_t>());
void unreference() noexcept {
uv_unref(as_uv_handle());
}
/**
* @brief Checks if the given handle referenced.
* @return True if the handle referenced, false otherwise.
*/
bool referenced() const noexcept override {
return !(uv_has_ref(this->template get<uv_handle_t>()) == 0);
[[nodiscard]] bool referenced() const noexcept {
return !!uv_has_ref(as_uv_handle());
}
/**
* @brief Returns the size of the underlying handle type.
* @return The size of the underlying handle type.
*/
std::size_t size() const noexcept {
return uv_handle_size(this->template get<uv_handle_t>()->type);
[[nodiscard]] std::size_t size() const noexcept {
return uv_handle_size(as_uv_handle()->type);
}
/**
@ -158,16 +156,17 @@ public:
*
* Gets the size of the send buffer that the operating system uses for the
* socket.<br/>
* This function works for TcpHandle, PipeHandle and UDPHandle handles on
* Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
* This function works for tcp, pipeand udp handles on Unix and for tcp and
* udp handles on Windows.<br/>
* Note that Linux will return double the size of the original set value.
*
* @return The size of the send buffer, 0 in case of errors.
* @return The size of the send buffer, the underlying return value in case
* of errors.
*/
int sendBufferSize() {
[[nodiscard]] int send_buffer_size() {
int value = 0;
auto err = uv_send_buffer_size(this->template get<uv_handle_t>(), &value);
return err ? 0 : value;
auto err = uv_send_buffer_size(as_uv_handle(), &value);
return err ? err : value;
}
/**
@ -175,14 +174,14 @@ public:
*
* Sets the size of the send buffer that the operating system uses for the
* socket.<br/>
* This function works for TcpHandle, PipeHandle and UDPHandle handles on
* Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
* This function works for tcp, pipe and udp handles on Unix and for tcp and
* udp handles on Windows.<br/>
* Note that Linux will set double the size.
*
* @return True in case of success, false otherwise.
* @return Underlying return value.
*/
bool sendBufferSize(int value) {
return (0 == uv_send_buffer_size(this->template get<uv_handle_t>(), &value));
[[nodiscard]] int send_buffer_size(int value) {
return uv_send_buffer_size(as_uv_handle(), &value);
}
/**
@ -190,16 +189,17 @@ public:
*
* Gets the size of the receive buffer that the operating system uses for
* the socket.<br/>
* This function works for TcpHandle, PipeHandle and UDPHandle handles on
* Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
* This function works for tcp, pipe and udp handles on Unix and for tcp and
* udp handles on Windows.<br/>
* Note that Linux will return double the size of the original set value.
*
* @return The size of the receive buffer, 0 in case of errors.
* @return The size of the receive buffer, the underlying return value in
* case of errors.
*/
int recvBufferSize() {
[[nodiscard]] int recv_buffer_size() {
int value = 0;
auto err = uv_recv_buffer_size(this->template get<uv_handle_t>(), &value);
return err ? 0 : value;
auto err = uv_recv_buffer_size(as_uv_handle(), &value);
return err ? err : value;
}
/**
@ -207,14 +207,14 @@ public:
*
* Sets the size of the receive buffer that the operating system uses for
* the socket.<br/>
* This function works for TcpHandle, PipeHandle and UDPHandle handles on
* Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
* This function works for tcp, pipe and udp handles on Unix and for tcp and
* udp handles on Windows.<br/>
* Note that Linux will set double the size.
*
* @return True in case of success, false otherwise.
* @return Underlying return value.
*/
bool recvBufferSize(int value) {
return (0 == uv_recv_buffer_size(this->template get<uv_handle_t>(), &value));
[[nodiscard]] int recv_buffer_size(int value) {
return uv_recv_buffer_size(as_uv_handle(), &value);
}
/**
@ -222,15 +222,14 @@ public:
*
* Supported handles:
*
* * TcpHandle
* * PipeHandle
* * TTYHandle
* * UDPHandle
* * PollHandle
* * tcp_handle
* * pipe_handle
* * tty_handle
* * udp_handle
* * poll_handle
*
* It will emit an ErrorEvent event if invoked on any other handle.<br/>
* If a handle doesnt have an attached file descriptor yet or the handle
* itself has been closed, an ErrorEvent event will be emitted.
* If invoked on a different handle, one that doesnt have an attached file
* descriptor yet or one which was closed, an invalid value is returned.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/handle.html#c.uv_fileno)
@ -239,12 +238,13 @@ public:
* @return The file descriptor attached to the hande or a negative value in
* case of errors.
*/
OSFileDescriptor fileno() const {
[[nodiscard]] os_file_descriptor fd() const {
uv_os_fd_t fd;
uv_fileno(this->template get<uv_handle_t>(), &fd);
uv_fileno(as_uv_handle(), &fd);
return fd;
}
};
} // namespace uvw
}
#endif // UVW_HANDLE_INCLUDE_H

2
src/uvw/idle.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "idle.h"
#include "idle.ipp"

65
src/uvw/idle.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef UVW_IDLE_INCLUDE_H
#define UVW_IDLE_INCLUDE_H
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
namespace uvw {
/*! @brief Idle event. */
struct idle_event {};
/**
* @brief The idle handle.
*
* Idle handles will emit a idle event once per loop iteration, right before the
* prepare handles.
*
* The notable difference with prepare handles is that when there are active
* idle handles, the loop will perform a zero timeout poll instead of blocking
* for I/O.
*
* @note
* Despite the name, idle handles will emit events on every loop iteration, not
* when the loop is actually _idle_.
*
* To create an `idle_handle` through a `loop`, no arguments are required.
*/
class idle_handle final: public handle<idle_handle, uv_idle_t, idle_event> {
static void start_callback(uv_idle_t *hndl);
public:
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts the handle.
*
* An idle event will be emitted once per loop iteration, right before
* polling the prepare handles.
*
* @return Underlying return value.
*/
int start();
/**
* @brief Stops the handle.
*
* @return Underlying return value.
*/
int stop();
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "idle.ipp"
#endif
#endif // UVW_IDLE_INCLUDE_H

View File

@ -1,73 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief IdleEvent event.
*
* It will be emitted by IdleHandle according with its functionalities.
*/
struct IdleEvent {};
/**
* @brief The IdleHandle handle.
*
* Idle handles will emit a IdleEvent event once per loop iteration, right
* before the PrepareHandle handles.
*
* The notable difference with prepare handles is that when there are active
* idle handles, the loop will perform a zero timeout poll instead of blocking
* for I/O.
*
* **Note**: despite the name, idle handles will emit events on every loop
* iteration, not when the loop is actually _idle_.
*
* To create an `IdleHandle` through a `Loop`, no arguments are required.
*/
class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
static void startCallback(uv_idle_t *handle) {
IdleHandle &idle = *(static_cast<IdleHandle*>(handle->data));
idle.publish(IdleEvent{});
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_idle_init);
}
/**
* @brief Starts the handle.
*
* A IdleEvent event will be emitted once per loop iteration, right before
* polling the PrepareHandle handles.
*/
void start() {
invoke(&uv_idle_start, get(), &startCallback);
}
/**
* @brief Stops the handle.
*/
void stop() {
invoke(&uv_idle_stop, get());
}
};
}

22
src/uvw/idle.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void idle_handle::start_callback(uv_idle_t *hndl) {
idle_handle &idle = *(static_cast<idle_handle *>(hndl->data));
idle.publish(idle_event{});
}
UVW_INLINE int idle_handle::init() {
return leak_if(uv_idle_init(parent().raw(), raw()));
}
UVW_INLINE int idle_handle::start() {
return uv_idle_start(raw(), &start_callback);
}
UVW_INLINE int idle_handle::stop() {
return uv_idle_stop(raw());
}
} // namespace uvw

2
src/uvw/lib.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "lib.h"
#include "lib.ipp"

68
src/uvw/lib.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef UVW_LIB_INCLUDE_H
#define UVW_LIB_INCLUDE_H
#include <memory>
#include <string>
#include <type_traits>
#include <uv.h>
#include "config.h"
#include "loop.h"
#include "uv_type.hpp"
namespace uvw {
/**
* @brief The shared lib class.
*
* `uvw` provides cross platform utilities for loading shared libraries and
* retrieving symbols from them, by means of the API offered by `libuv`.
*/
class shared_lib final: public uv_type<uv_lib_t> {
public:
explicit shared_lib(loop::token token, std::shared_ptr<loop> ref, const std::string &filename) noexcept;
~shared_lib() noexcept;
/**
* @brief Checks if the library has been correctly opened.
* @return True if the library is opened, false otherwise.
*/
explicit operator bool() const noexcept;
/**
* @brief Retrieves a data pointer from a dynamic library.
*
* `F` shall be a valid function type (as an example, `void(int)`).<br/>
* It is legal for a symbol to map to `nullptr`.
*
* @param name The symbol to be retrieved.
* @return A valid function pointer in case of success, `nullptr` otherwise.
*/
template<typename F>
F *sym(const std::string &name) {
static_assert(std::is_function_v<F>);
F *func;
auto err = uv_dlsym(raw(), name.data(), reinterpret_cast<void **>(&func));
if(err) {
func = nullptr;
}
return func;
}
/**
* @brief Returns the last error message, if any.
* @return The last error message, if any.
*/
[[nodiscard]] const char *error() const noexcept;
private:
bool opened;
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "lib.ipp"
#endif
#endif // UVW_LIB_INCLUDE_H

View File

@ -1,94 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <string>
#include <type_traits>
#include <uv.h>
#include "loop.hpp"
namespace uvw {
/**
* @brief The SharedLib class.
*
* `uvw` provides cross platform utilities for loading shared libraries and
* retrieving symbols from them, by means of the API offered by `libuv`.
*/
class SharedLib final {
explicit SharedLib(std::shared_ptr<Loop> ref, std::string filename) noexcept
: pLoop{std::move(ref)}, lib{}
{
opened = (0 == uv_dlopen(filename.data(), &lib));
}
public:
/**
* @brief Creates a new shared library object.
* @param loop A pointer to the loop from which the handle generated.
* @param filename The filename of the library in UTF8.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<SharedLib> create(std::shared_ptr<Loop> loop, std::string filename) noexcept {
return std::shared_ptr<SharedLib>{new SharedLib{std::move(loop), std::move(filename)}};
}
SharedLib(const SharedLib &) = delete;
SharedLib(SharedLib &&) = delete;
~SharedLib() noexcept {
uv_dlclose(&lib);
}
SharedLib& operator=(const SharedLib &) = delete;
SharedLib& operator=(SharedLib &&) = delete;
/**
* @brief Checks if the library has been correctly opened.
* @return True if the library is opened, false otherwise.
*/
explicit operator bool() const noexcept { return !opened; }
/**
* @brief Retrieves a data pointer from a dynamic library.
*
* `F` shall be a valid function type (as an example, `void(int)`).<br/>
* It is legal for a symbol to map to `nullptr`.
*
* @param name The symbol to be retrieved.
* @return A valid function pointer in case of success, `nullptr` otherwise.
*/
template<typename F>
F * sym(std::string name) {
static_assert(std::is_function<F>::value, "!");
F *func;
auto err = uv_dlsym(&lib, name.data(), reinterpret_cast<void**>(&func));
if(err) { func = nullptr; }
return func;
}
/**
* @brief Returns the last error message, if any.
* @return The last error message, if any.
*/
const char * error() const noexcept {
return uv_dlerror(&lib);
}
/**
* @brief Gets the loop from which the object was originated.
* @return A reference to a loop instance.
*/
Loop& loop() const noexcept { return *pLoop; }
private:
std::shared_ptr<Loop> pLoop;
uv_lib_t lib;
bool opened;
};
}

23
src/uvw/lib.ipp Normal file
View File

@ -0,0 +1,23 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE shared_lib::shared_lib(loop::token token, std::shared_ptr<loop> ref, const std::string &filename) noexcept
: uv_type{token, std::move(ref)} {
opened = (0 == uv_dlopen(filename.data(), raw()));
}
UVW_INLINE shared_lib::~shared_lib() noexcept {
uv_dlclose(raw());
}
UVW_INLINE shared_lib::operator bool() const noexcept {
return opened;
}
UVW_INLINE const char *shared_lib::error() const noexcept {
return uv_dlerror(raw());
}
} // namespace uvw

2
src/uvw/loop.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "loop.h"
#include "loop.ipp"

439
src/uvw/loop.h Normal file
View File

@ -0,0 +1,439 @@
#ifndef UVW_LOOP_INCLUDE_H
#define UVW_LOOP_INCLUDE_H
#ifdef _WIN32
# include <ciso646>
#endif
#include <chrono>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include <uv.h>
#include "config.h"
#include "emitter.h"
#include "util.h"
namespace uvw {
class async_handle;
class check_handle;
class fs_event_handle;
class fs_poll_handle;
class idle_handle;
class pipe_handle;
class poll_handle;
class prepare_handle;
class process_handle;
class signal_handle;
class tcp_handle;
class timer_handle;
class tty_handle;
class udp_handle;
namespace details {
enum class uvw_loop_option : std::underlying_type_t<uv_loop_option> {
BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL,
IDLE_TIME = UV_METRICS_IDLE_TIME
};
enum class uvw_run_mode : std::underlying_type_t<uv_run_mode> {
DEFAULT = UV_RUN_DEFAULT,
ONCE = UV_RUN_ONCE,
NOWAIT = UV_RUN_NOWAIT
};
} // namespace details
using metrics_type = uv_metrics_t; /*!< Library equivalent for uv_metrics_t. */
/**
* @brief The loop class.
*
* The event loop is the central part of `uvw`'s functionalities, as well as
* `libuv`'s ones.<br/>
* It takes care of polling for I/O and scheduling callbacks to be run based on
* different sources of events.
*/
class loop final: public emitter<loop>, public std::enable_shared_from_this<loop> {
using deleter = void (*)(uv_loop_t *);
template<typename, typename, typename...>
friend class resource;
class uv_token {
friend class loop;
explicit uv_token(int) {}
};
template<typename Type>
auto init(int, Type &value) -> decltype(value.init()) {
return value.init();
}
template<typename Type>
int init(char, Type &) {
return 0;
}
loop(std::unique_ptr<uv_loop_t, deleter> ptr) noexcept;
public:
using token = uv_token;
using time = std::chrono::duration<uint64_t, std::milli>;
using option = details::uvw_loop_option;
using run_mode = details::uvw_run_mode;
/**
* @brief Initializes a new loop instance.
* @return A pointer to the newly created loop.
*/
static std::shared_ptr<loop> create();
/**
* @brief Initializes a new loop instance from an existing resource.
*
* The lifetime of the resource must exceed that of the instance to which
* it's associated. Management of the memory associated with the resource is
* in charge of the user.
*
* @param res A valid pointer to a correctly initialized resource.
* @return A pointer to the newly created loop.
*/
static std::shared_ptr<loop> create(uv_loop_t *res);
/**
* @brief Gets the initialized default loop.
*
* It may return an empty pointer in case of failure.<br>
* This function is just a convenient way for having a global loop
* throughout an application, the default loop is in no way different than
* the ones initialized with `create()`.<br>
* As such, the default loop can be closed with `close()` so the resources
* associated with it are freed (even if it is not strictly necessary).
*
* @return The initialized default loop.
*/
static std::shared_ptr<loop> get_default();
loop(const loop &) = delete;
loop(loop &&other) = delete;
loop &operator=(const loop &) = delete;
loop &operator=(loop &&other) = delete;
~loop() noexcept override;
/**
* @brief Sets additional loop options.
*
* You should normally call this before the first call to uv_run() unless
* mentioned otherwise.<br/>
* Supported options:
*
* * `loop::option::BLOCK_SIGNAL`: Block a signal when polling for new
* events. A second argument is required and it is the signal number.
* * `loop::option::IDLE_TIME`: Accumulate the amount of idle time the event
* loop spends in the event provider. This option is necessary to use
* `idle_time()`.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_configure)
* for further details.
*
* @return Underlying return value.
*/
template<typename... Args>
int configure(option flag, Args &&...args) {
return uv_loop_configure(uv_loop.get(), static_cast<uv_loop_option>(flag), std::forward<Args>(args)...);
}
/**
* @brief Creates resources of any type.
*
* This should be used as a default method to create resources.<br/>
* The arguments are the ones required for the specific resource.
*
* Use it as `loop->resource<uvw::timer_handle>()`.
*
* @return A pointer to the newly created resource.
*/
template<typename R, typename... Args>
std::shared_ptr<R> resource(Args &&...args) {
auto ptr = uninitialized_resource<R>(std::forward<Args>(args)...);
return (init(0, *ptr) == 0) ? ptr : nullptr;
}
/**
* @brief Creates uninitialized resources of any type.
* @return A pointer to the newly created resource.
*/
template<typename R, typename... Args>
std::shared_ptr<R> uninitialized_resource(Args &&...args) {
return std::make_shared<R>(token{0}, shared_from_this(), std::forward<Args>(args)...);
}
/**
* @brief Releases all internal loop resources.
*
* Call this function only when the loop has finished executing and all open
* handles and requests have been closed, or the loop will error.
*
* @return Underlying return value.
*/
int close();
/**
* @brief Runs the event loop.
*
* Available modes are:
*
* * `loop::run_mode::DEFAULT`: Runs the event loop until there are no more
* active and referenced handles or requests.
* * `loop::run_mode::ONCE`: Poll for i/o once. Note that this function
* blocks if there are no pending callbacks.
* * `loop::run_mode::NOWAIT`: Poll for i/o once but dont block if there
* are no pending callbacks.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_run)
* for further details.
*
* @return Underlying return value.
*/
int run(run_mode mode = run_mode::DEFAULT) noexcept;
/**
* @brief Checks if there are active resources.
* @return True if there are active resources in the loop.
*/
bool alive() const noexcept;
/**
* @brief Stops the event loop.
*
* It causes `run()` to end as soon as possible.<br/>
* This will happen not sooner than the next loop iteration.<br/>
* If this function was called before blocking for I/O, the loop wont block
* for I/O on this iteration.
*/
void stop() noexcept;
/**
* @brief Get backend file descriptor.
*
* Only kqueue, epoll and event ports are supported.<br/>
* This can be used in conjunction with `run(loop::run_mode::NOWAIT)` to
* poll in one thread and run the event loops callbacks in another.
*
* @return The backend file descriptor.
*/
int descriptor() const noexcept;
/**
* @brief Gets the poll timeout.
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of valid timeout, false otherwise.
* * Milliseconds (`std::chrono::duration<uint64_t, std::milli>`).
*/
std::pair<bool, time> timeout() const noexcept;
/**
* @brief Returns the amount of time the event loop has been idle. The call
* is thread safe.
* @return The accumulated time spent idle.
*/
time idle_time() const noexcept;
/**
* @brief Tracks various internal operations of the event loop.
* @return Event loop metrics.
*/
metrics_type metrics() const noexcept;
/**
* @brief Returns the current timestamp in milliseconds.
*
* The timestamp is cached at the start of the event loop tick.<br/>
* The timestamp increases monotonically from some arbitrary point in
* time.<br/>
* Dont make assumptions about the starting point, you will only get
* disappointed.
*
* @return The current timestamp in milliseconds (actual type is
* `std::chrono::duration<uint64_t, std::milli>`).
*/
time now() const noexcept;
/**
* @brief Updates the event loops concept of _now_.
*
* The current time is cached at the start of the event loop tick in order
* to reduce the number of time-related system calls.<br/>
* You wont normally need to call this function unless you have callbacks
* that block the event loop for longer periods of time, where _longer_ is
* somewhat subjective but probably on the order of a millisecond or more.
*/
void update() const noexcept;
/**
* @brief Walks the list of handles.
*
* The callback is invoked once for each handle that is still active.
*
* @param callback A function to invoke once for each active handle.
*/
template<typename Func>
void walk(Func callback) {
auto func = [](uv_handle_t *hndl, void *callback_func) {
if(hndl->data) {
auto &cb = *static_cast<Func *>(callback_func);
switch(utilities::guess_handle(handle_category{hndl->type})) {
case handle_type::ASYNC:
cb(*static_cast<async_handle *>(hndl->data));
break;
case handle_type::CHECK:
cb(*static_cast<check_handle *>(hndl->data));
break;
case handle_type::FS_EVENT:
cb(*static_cast<fs_event_handle *>(hndl->data));
break;
case handle_type::FS_POLL:
cb(*static_cast<fs_poll_handle *>(hndl->data));
break;
case handle_type::IDLE:
cb(*static_cast<idle_handle *>(hndl->data));
break;
case handle_type::PIPE:
cb(*static_cast<pipe_handle *>(hndl->data));
break;
case handle_type::POLL:
cb(*static_cast<poll_handle *>(hndl->data));
break;
case handle_type::PREPARE:
cb(*static_cast<prepare_handle *>(hndl->data));
break;
case handle_type::PROCESS:
cb(*static_cast<process_handle *>(hndl->data));
break;
case handle_type::SIGNAL:
cb(*static_cast<signal_handle *>(hndl->data));
break;
case handle_type::TCP:
cb(*static_cast<tcp_handle *>(hndl->data));
break;
case handle_type::TIMER:
cb(*static_cast<timer_handle *>(hndl->data));
break;
case handle_type::TTY:
cb(*static_cast<tty_handle *>(hndl->data));
break;
case handle_type::UDP:
cb(*static_cast<udp_handle *>(hndl->data));
break;
default:
// this handle isn't managed by uvw, let it be...
break;
}
}
};
uv_walk(uv_loop.get(), func, &callback);
}
/**
* @brief Reinitialize any kernel state necessary in the child process after
* a fork(2) system call.
*
* Previously started watchers will continue to be started in the child
* process.
*
* It is necessary to explicitly call this function on every event loop
* created in the parent process that you plan to continue to use in the
* child, including the default loop (even if you dont continue to use it
* in the parent). This function must be called before calling any API
* function using the loop in the child. Failure to do so will result in
* undefined behaviour, possibly including duplicate events delivered to
* both parent and child or aborting the child process.
*
* When possible, it is preferred to create a new loop in the child process
* instead of reusing a loop created in the parent. New loops created in the
* child process after the fork should not use this function.
*
* Note that this function is not implemented on Windows.<br/>
* Note also that this function is experimental in `libuv`. It may contain
* bugs, and is subject to change or removal. API and ABI stability is not
* guaranteed.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_fork)
* for further details.
*
* @return Underlying return value.
*/
int fork() noexcept;
/**
* @brief Gets user-defined data. `uvw` won't use this field in any case.
* @return User-defined data if any, an invalid pointer otherwise.
*/
template<typename R = void>
std::shared_ptr<R> data() const {
return std::static_pointer_cast<R>(user_data);
}
/**
* @brief Sets arbitrary data. `uvw` won't use this field in any case.
* @param ud User-defined arbitrary data.
*/
void data(std::shared_ptr<void> ud);
/**
* @brief Gets the underlying raw data structure.
*
* This function should not be used, unless you know exactly what you are
* doing and what are the risks.<br/>
* Going raw is dangerous, mainly because the lifetime management of a loop,
* a handle or a request is in charge to the library itself and users should
* not work around it.
*
* @warning
* Use this function at your own risk, but do not expect any support in case
* of bugs.
*
* @return The underlying raw data structure.
*/
const uv_loop_t *raw() const noexcept;
/**
* @brief Gets the underlying raw data structure.
*
* This function should not be used, unless you know exactly what you are
* doing and what are the risks.<br/>
* Going raw is dangerous, mainly because the lifetime management of a loop,
* a handle or a request is in charge to the library itself and users should
* not work around it.
*
* @warning
* Use this function at your own risk, but do not expect any support in case
* of bugs.
*
* @return The underlying raw data structure.
*/
uv_loop_t *raw() noexcept;
private:
std::unique_ptr<uv_loop_t, deleter> uv_loop;
std::shared_ptr<void> user_data{nullptr};
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "loop.ipp"
#endif
#endif // UVW_LOOP_INCLUDE_H

View File

@ -1,417 +0,0 @@
#pragma once
#ifdef _WIN32
#include <ciso646>
#endif
#include <functional>
#include <memory>
#include <utility>
#include <type_traits>
#include <chrono>
#include <uv.h>
#include "emitter.hpp"
namespace uvw {
namespace details {
enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
};
enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
DEFAULT = UV_RUN_DEFAULT,
ONCE = UV_RUN_ONCE,
NOWAIT = UV_RUN_NOWAIT
};
}
/**
* @brief Untyped handle class
*
* Handles' types are unknown from the point of view of the loop.<br/>
* Anyway, a loop maintains a list of all the associated handles and let the
* users walk them as untyped instances.<br/>
* This can help to end all the pending requests by closing the handles.
*/
class BaseHandle {
public:
/**
* @brief Checks if the handle is active.
*
* What _active_ means depends on the type of handle:
*
* * An AsyncHandle handle is always active and cannot be deactivated,
* except by closing it with uv_close().
* * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
* that deals with I/O - is active when it is doing something that involves
* I/O, like reading, writing, connecting, accepting new connections, etc.
* * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
* has been started with a call to `start()`.
*
* Rule of thumb: if a handle of type `FooHandle` has a `start()` member
* method, then its active from the moment that method is called. Likewise,
* `stop()` deactivates the handle again.
*
* @return True if the handle is active, false otherwise.
*/
virtual bool active() const noexcept = 0;
/**
* @brief Checks if a handle is closing or closed.
*
* This function should only be used between the initialization of the
* handle and the arrival of the close callback.
*
* @return True if the handle is closing or closed, false otherwise.
*/
virtual bool closing() const noexcept = 0;
/**
* @brief Reference the given handle.
*
* References are idempotent, that is, if a handle is already referenced
* calling this function again will have no effect.
*/
virtual void reference() noexcept = 0;
/**
* @brief Unreference the given handle.
*
* References are idempotent, that is, if a handle is not referenced calling
* this function again will have no effect.
*/
virtual void unreference() noexcept = 0;
/**
* @brief Checks if the given handle referenced.
* @return True if the handle referenced, false otherwise.
*/
virtual bool referenced() const noexcept = 0;
/**
* @brief Request handle to be closed.
*
* This **must** be called on each handle before memory is released.<br/>
* In-progress requests are cancelled and this can result in an ErrorEvent
* emitted.
*/
virtual void close() noexcept = 0;
};
/**
* @brief The Loop class.
*
* The event loop is the central part of `uvw`'s functionalities, as well as
* `libuv`'s ones.<br/>
* It takes care of polling for I/O and scheduling callbacks to be run based on
* different sources of events.
*/
class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
using Deleter = void(*)(uv_loop_t *);
template<typename, typename>
friend class Resource;
Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept
: loop{std::move(ptr)}
{}
public:
using Time = std::chrono::duration<uint64_t, std::milli>;
using Configure = details::UVLoopOption;
using Mode = details::UVRunMode;
/**
* @brief Initializes a new Loop instance.
* @return A pointer to the newly created loop.
*/
static std::shared_ptr<Loop> create() {
auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};
auto loop = std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
if(uv_loop_init(loop->loop.get())) {
loop = nullptr;
}
return loop;
}
/**
* @brief Gets the initialized default loop.
*
* It may return an empty pointer in case of failure.<br>
* This function is just a convenient way for having a global loop
* throughout an application, the default loop is in no way different than
* the ones initialized with `create()`.<br>
* As such, the default loop can be closed with `close()` so the resources
* associated with it are freed (even if it is not strictly necessary).
*
* @return The initialized default loop.
*/
static std::shared_ptr<Loop> getDefault() {
static std::weak_ptr<Loop> ref;
std::shared_ptr<Loop> loop;
if(ref.expired()) {
auto def = uv_default_loop();
if(def) {
auto ptr = std::unique_ptr<uv_loop_t, Deleter>(def, [](uv_loop_t *){});
loop = std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
}
ref = loop;
} else {
loop = ref.lock();
}
return loop;
}
Loop(const Loop &) = delete;
Loop(Loop &&other) = delete;
Loop& operator=(const Loop &) = delete;
Loop& operator=(Loop &&other) = delete;
~Loop() noexcept {
if(loop) {
close();
}
}
/**
* @brief Sets additional loop options.
*
* You should normally call this before the first call to uv_run() unless
* mentioned otherwise.<br/>
* Supported options:
*
* * `Loop::Configure::BLOCK_SIGNAL`: Block a signal when polling for new
* events. A second argument is required and it is the signal number.
*
* An ErrorEvent will be emitted in case of errors.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_configure)
* for further details.
*/
template<typename... Args>
void configure(Configure flag, Args&&... args) {
auto err = uv_loop_configure(loop.get(), static_cast<std::underlying_type_t<Configure>>(flag), std::forward<Args>(args)...);
if(err) { publish(ErrorEvent{err}); }
}
/**
* @brief Creates resources of handles' types.
*
* This should be used as a default method to create resources.<br/>
* The arguments are the ones required for the specific resource.
*
* Use it as `loop->resource<uvw::TimerHandle>()`.
*
* @return A pointer to the newly created resource.
*/
template<typename R, typename... 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;
}
/**
* @brief Creates resources of types other than handles' ones.
*
* This should be used as a default method to create resources.<br/>
* The arguments are the ones required for the specific resource.
*
* Use it as `loop->resource<uvw::WorkReq>()`.
*
* @return A pointer to the newly created resource.
*/
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)...);
}
/**
* @brief Releases all internal loop resources.
*
* Call this function only when the loop has finished executing and all open
* handles and requests have been closed, or the loop will emit an error.
*
* An ErrorEvent will be emitted in case of errors.
*/
void close() {
auto err = uv_loop_close(loop.get());
if(err) { publish(ErrorEvent{err}); }
}
/**
* @brief Runs the event loop.
*
* Available modes are:
*
* * `Loop::Mode::DEFAULT`: Runs the event loop until there are no more
* active and referenced handles or requests.
* * `Loop::Mode::ONCE`: Poll for i/o once. Note that this function blocks
* if there are no pending callbacks.
* * `Loop::Mode::NOWAIT`: Poll for i/o once but dont block if there are no
* pending callbacks.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_run)
* for further details.
*
* @return True when done, false in all other cases.
*/
template<Mode mode = Mode::DEFAULT>
bool run() noexcept {
auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
auto uvrm = static_cast<uv_run_mode>(utm);
return (uv_run(loop.get(), uvrm) == 0);
}
/**
* @brief Checks if there are active resources.
* @return True if there are active resources in the loop.
*/
bool alive() const noexcept {
return !(uv_loop_alive(loop.get()) == 0);
}
/**
* @brief Stops the event loop.
*
* It causes `run()` to end as soon as possible.<br/>
* This will happen not sooner than the next loop iteration.<br/>
* If this function was called before blocking for I/O, the loop wont block
* for I/O on this iteration.
*/
void stop() noexcept {
uv_stop(loop.get());
}
/**
* @brief Get backend file descriptor.
*
* Only kqueue, epoll and event ports are supported.<br/>
* This can be used in conjunction with `run<Loop::Mode::NOWAIT>()` to poll
* in one thread and run the event loops callbacks in another.
*
* @return The backend file descriptor.
*/
int descriptor() const noexcept {
return uv_backend_fd(loop.get());
}
/**
* @brief Gets the poll timeout.
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of valid timeout, false otherwise.
* * Milliseconds (`std::chrono::duration<uint64_t, std::milli>`).
*/
std::pair<bool, Time> timeout() const noexcept {
auto to = uv_backend_timeout(loop.get());
return std::make_pair(to == -1, Time{to});
}
/**
* @brief Returns the current timestamp in milliseconds.
*
* The timestamp is cached at the start of the event loop tick.<br/>
* The timestamp increases monotonically from some arbitrary point in
* time.<br/>
* Dont make assumptions about the starting point, you will only get
* disappointed.
*
* @return The current timestamp in milliseconds (actual type is
* `std::chrono::duration<uint64_t, std::milli>`).
*/
Time now() const noexcept {
return Time{uv_now(loop.get())};
}
/**
* @brief Updates the event loops concept of _now_.
*
* The current time is cached at the start of the event loop tick in order
* to reduce the number of time-related system calls.<br/>
* You wont normally need to call this function unless you have callbacks
* that block the event loop for longer periods of time, where _longer_ is
* somewhat subjective but probably on the order of a millisecond or more.
*/
void update() const noexcept {
return uv_update_time(loop.get());
}
/**
* @brief Walks the list of handles.
*
* The callback will be executed once for each handle that is still active.
*
* @param callback A function to be invoked once for each active handle.
*/
void walk(std::function<void(BaseHandle &)> callback) {
// remember: non-capturing lambdas decay to pointers to functions
uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
std::function<void(BaseHandle &)> &f =
*static_cast<std::function<void(BaseHandle &)>*>(func);
f(ref);
}, &callback);
}
/**
* @brief Reinitialize any kernel state necessary in the child process after
* a fork(2) system call.
*
* Previously started watchers will continue to be started in the child
* process.
*
* It is necessary to explicitly call this function on every event loop
* created in the parent process that you plan to continue to use in the
* child, including the default loop (even if you dont continue to use it
* in the parent). This function must be called before calling any API
* function using the loop in the child. Failure to do so will result in
* undefined behaviour, possibly including duplicate events delivered to
* both parent and child or aborting the child process.
*
* When possible, it is preferred to create a new loop in the child process
* instead of reusing a loop created in the parent. New loops created in the
* child process after the fork should not use this function.
*
* Note that this function is not implemented on Windows.<br/>
* Note also that this function is experimental in `libuv`. It may contain
* bugs, and is subject to change or removal. API and ABI stability is not
* guaranteed.
*
* An ErrorEvent will be emitted in case of errors.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_fork)
* for further details.
*/
void fork() noexcept {
auto err = uv_loop_fork(loop.get());
if(err) { publish(ErrorEvent{err}); }
}
private:
std::unique_ptr<uv_loop_t, Deleter> loop;
};
}

116
src/uvw/loop.ipp Normal file
View File

@ -0,0 +1,116 @@
#include "config.h"
namespace uvw {
UVW_INLINE loop::loop(std::unique_ptr<uv_loop_t, deleter> ptr) noexcept
: uv_loop{std::move(ptr)} {}
UVW_INLINE std::shared_ptr<loop> loop::create() {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{new uv_loop_t, [](uv_loop_t *l) { delete l; }};
auto curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
if(uv_loop_init(curr->uv_loop.get())) {
curr = nullptr;
}
return curr;
}
UVW_INLINE std::shared_ptr<loop> loop::create(uv_loop_t *res) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>{res, [](uv_loop_t *) {}};
return std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
UVW_INLINE std::shared_ptr<loop> loop::get_default() {
static std::weak_ptr<loop> ref;
std::shared_ptr<loop> curr;
if(ref.expired()) {
auto def = uv_default_loop();
if(def) {
auto ptr = std::unique_ptr<uv_loop_t, deleter>(def, [](uv_loop_t *) {});
curr = std::shared_ptr<loop>{new loop{std::move(ptr)}};
}
ref = curr;
} else {
curr = ref.lock();
}
return curr;
}
UVW_INLINE loop::~loop() noexcept {
if(uv_loop) {
close();
}
}
UVW_INLINE int loop::close() {
int ret = 0;
if(uv_loop) {
ret = uv_loop_close(uv_loop.get());
uv_loop.reset();
}
return ret;
}
UVW_INLINE int loop::run(run_mode mode) noexcept {
return uv_run(uv_loop.get(), static_cast<uv_run_mode>(mode));
}
UVW_INLINE bool loop::alive() const noexcept {
return !!uv_loop_alive(uv_loop.get());
}
UVW_INLINE void loop::stop() noexcept {
uv_stop(uv_loop.get());
}
UVW_INLINE int loop::descriptor() const noexcept {
return uv_backend_fd(uv_loop.get());
}
UVW_INLINE std::pair<bool, loop::time> loop::timeout() const noexcept {
auto to = uv_backend_timeout(uv_loop.get());
return std::make_pair(to == -1, time{to});
}
UVW_INLINE loop::time loop::idle_time() const noexcept {
return time{uv_metrics_idle_time(uv_loop.get())};
}
UVW_INLINE metrics_type loop::metrics() const noexcept {
metrics_type res{};
uv_metrics_info(uv_loop.get(), &res);
return res;
}
UVW_INLINE loop::time loop::now() const noexcept {
return time{uv_now(uv_loop.get())};
}
UVW_INLINE void loop::update() const noexcept {
return uv_update_time(uv_loop.get());
}
UVW_INLINE int loop::fork() noexcept {
return uv_loop_fork(uv_loop.get());
}
UVW_INLINE void loop::data(std::shared_ptr<void> ud) {
user_data = std::move(ud);
}
UVW_INLINE const uv_loop_t *loop::raw() const noexcept {
return uv_loop.get();
}
UVW_INLINE uv_loop_t *loop::raw() noexcept {
return const_cast<uv_loop_t *>(const_cast<const loop *>(this)->raw());
}
} // namespace uvw

2
src/uvw/pipe.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "pipe.h"
#include "pipe.ipp"

View File

@ -1,44 +1,51 @@
#pragma once
#ifndef UVW_PIPE_INCLUDE_H
#define UVW_PIPE_INCLUDE_H
#include <type_traits>
#include <utility>
#include <memory>
#include <string>
#include <type_traits>
#include <uv.h>
#include "config.h"
#include "enum.hpp"
#include "loop.h"
#include "request.hpp"
#include "stream.hpp"
#include "util.hpp"
#include "loop.hpp"
#include "stream.h"
#include "util.h"
namespace uvw {
namespace details {
enum class uvw_chmod_flags : std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
UVW_ENUM = 0
};
}
/**
* @brief The PipeHandle handle.
* @brief The pipe handle.
*
* Pipe handles provide an abstraction over local domain sockets on Unix and
* named pipes on Windows.
*
* To create a `PipeHandle` through a `Loop`, arguments follow:
* To create a `pipe_handle` through a `loop`, arguments follow:
*
* * An optional boolean value that indicates if this pipe will be used for
* handle passing between processes.
*/
class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
class pipe_handle final: public stream_handle<pipe_handle, uv_pipe_t> {
public:
explicit PipeHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, bool pass = false)
: StreamHandle{std::move(ca), std::move(ref)}, ipc{pass}
{}
using chmod_flags = details::uvw_chmod_flags;
explicit pipe_handle(loop::token token, std::shared_ptr<loop> ref, bool pass = false);
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
* @return Underlying return value.
*/
bool init() {
return initialize(&uv_pipe_init, ipc);
}
int init();
/**
* @brief Opens an existing file descriptor or HANDLE as a pipe.
@ -47,10 +54,9 @@ public:
* its required that it represents a valid pipe.
*
* @param file A valid file handle (either a file descriptor or a HANDLE).
* @return Underlying return value.
*/
void open(FileHandle file) {
invoke(&uv_pipe_open, get(), file);
}
int open(file_handle file);
/**
* @brief bind Binds the pipe to a file path (Unix) or a name (Windows).
@ -58,37 +64,30 @@ public:
* Paths on Unix get truncated typically between 92 and 108 bytes.
*
* @param name A valid file path.
* @param no_truncate Force an error rather than allow truncating a path.
* @return Underlying return value.
*/
void bind(std::string name) {
invoke(&uv_pipe_bind, get(), name.data());
}
int bind(const std::string &name, const bool no_truncate = false);
/**
* @brief Connects to the Unix domain socket or the named pipe.
*
* Paths on Unix get truncated typically between 92 and 108 bytes.
* Paths on Unix get truncated typically between 92 and 108 bytes.<br/>
* A connect event is emitted when the connection has been
* established.
*
* @param name A valid domain socket or named pipe.
* @param no_truncate Force an error rather than allow truncating a path.
* @return Underlying return value.
*/
void connect(std::string name) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto connect = loop().resource<details::ConnectReq>();
connect->once<ErrorEvent>(listener);
connect->once<ConnectEvent>(listener);
connect->connect(&uv_pipe_connect, get(), name.data());
}
int connect(const std::string &name, const bool no_truncate = false);
/**
* @brief Gets the name of the Unix domain socket or the named pipe.
* @return The name of the Unix domain socket or the named pipe, an empty
* string in case of errors.
*/
std::string sock() const noexcept {
return details::tryRead(&uv_pipe_getsockname, get());
}
std::string sock() const noexcept;
/**
* @brief Gets the name of the Unix domain socket or the named pipe to which
@ -96,9 +95,7 @@ public:
* @return The name of the Unix domain socket or the named pipe to which
* the handle is connected, an empty string in case of errors.
*/
std::string peer() const noexcept {
return details::tryRead(&uv_pipe_getpeername, get());
}
std::string peer() const noexcept;
/**
* @brief Sets the number of pending pipe this instance can handle.
@ -109,17 +106,13 @@ public:
*
* @param count The number of accepted pending pipe.
*/
void pending(int count) noexcept {
uv_pipe_pending_instances(get(), count);
}
void pending(int count) noexcept;
/**
* @brief Gets the number of pending pipe this instance can handle.
* @return The number of pending pipe this instance can handle.
*/
int pending() noexcept {
return uv_pipe_pending_count(get());
}
int pending() noexcept;
/**
* @brief Used to receive handles over IPC pipes.
@ -132,19 +125,40 @@ public:
*
* @return The type of the pending handle. Possible values are:
*
* * `HandleType::PIPE`
* * `HandleType::TCP`
* * `HandleType::UDP`
* * `HandleType::UNKNOWN`
* * `handle_type::PIPE`
* * `handle_type::TCP`
* * `handle_type::UDP`
* * `handle_type::UNKNOWN`
*/
HandleType receive() noexcept {
auto type = uv_pipe_pending_type(get());
return Utilities::guessHandle(type);
}
handle_type receive() noexcept;
/**
* @brief Alters pipe permissions.
*
* It allows the pipe to be accessed from processes run by different users.
*
* Available flags are:
*
* * `pipe_handle::chmod_flags::READABLE`
* * `pipe_handle::chmod_flags::WRITABLE`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_chmod)
* for further details.
*
* @param flags A valid set of flags.
* @return Underlying return value.
*/
int chmod(chmod_flags flags) noexcept;
private:
bool ipc;
};
} // namespace uvw
}
#ifndef UVW_AS_LIB
# include "pipe.ipp"
#endif
#endif // UVW_PIPE_INCLUDE_H

59
src/uvw/pipe.ipp Normal file
View File

@ -0,0 +1,59 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE pipe_handle::pipe_handle(loop::token token, std::shared_ptr<loop> ref, bool pass)
: stream_handle{token, std::move(ref)}, ipc{pass} {}
UVW_INLINE int pipe_handle::init() {
return leak_if(uv_pipe_init(parent().raw(), raw(), ipc));
}
UVW_INLINE int pipe_handle::open(file_handle file) {
return uv_pipe_open(raw(), file);
}
UVW_INLINE int pipe_handle::bind(const std::string &name, const bool no_truncate) {
return uv_pipe_bind2(raw(), name.data(), name.size(), no_truncate * UV_PIPE_NO_TRUNCATE);
}
UVW_INLINE int pipe_handle::connect(const std::string &name, const bool no_truncate) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto connect = parent().resource<details::connect_req>();
connect->on<error_event>(listener);
connect->on<connect_event>(listener);
unsigned int flags = no_truncate * UV_PIPE_NO_TRUNCATE;
return connect->connect(&uv_pipe_connect2, raw(), name.data(), name.size(), flags);
}
UVW_INLINE std::string pipe_handle::sock() const noexcept {
return details::try_read(&uv_pipe_getsockname, raw());
}
UVW_INLINE std::string pipe_handle::peer() const noexcept {
return details::try_read(&uv_pipe_getpeername, raw());
}
UVW_INLINE void pipe_handle::pending(int count) noexcept {
uv_pipe_pending_instances(raw(), count);
}
UVW_INLINE int pipe_handle::pending() noexcept {
return uv_pipe_pending_count(raw());
}
UVW_INLINE handle_type pipe_handle::receive() noexcept {
handle_category category = uv_pipe_pending_type(raw());
return utilities::guess_handle(category);
}
UVW_INLINE int pipe_handle::chmod(chmod_flags flags) noexcept {
return uv_pipe_chmod(raw(), static_cast<uv_poll_event>(flags));
}
} // namespace uvw

2
src/uvw/poll.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "poll.h"
#include "poll.ipp"

119
src/uvw/poll.h Normal file
View File

@ -0,0 +1,119 @@
#ifndef UVW_POLL_INCLUDE_H
#define UVW_POLL_INCLUDE_H
#include <memory>
#include <type_traits>
#include <uv.h>
#include "config.h"
#include "enum.hpp"
#include "handle.hpp"
#include "util.h"
namespace uvw {
namespace details {
enum class uvw_poll_event : std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT,
PRIORITIZED = UV_PRIORITIZED,
UVW_ENUM = 0
};
}
/*! @brief Poll event. */
struct poll_event {
explicit poll_event(details::uvw_poll_event events) noexcept;
/**
* @brief Detected events all in one.
*
* Available flags are:
*
* * `poll_handle::event::READABLE`
* * `poll_handle::event::WRITABLE`
* * `poll_handle::event::DISCONNECT`
* * `poll_handle::event::PRIORITIZED`
*/
details::uvw_poll_event flags;
};
/**
* @brief The poll handle.
*
* Poll handles are used to watch file descriptors for readability, writability
* and disconnection.
*
* To create a `poll_handle` through a `loop`, arguments follow:
*
* * A descriptor that can be:
* * either an `int` file descriptor
* * or a `os_socket_handle` socket descriptor
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/poll.html)
* for further details.
*/
class poll_handle final: public handle<poll_handle, uv_poll_t, poll_event> {
static void start_callback(uv_poll_t *hndl, int status, int events);
public:
using poll_event_flags = details::uvw_poll_event;
explicit poll_handle(loop::token token, std::shared_ptr<loop> ref, int desc);
explicit poll_handle(loop::token token, std::shared_ptr<loop> ref, os_socket_handle sock);
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts polling the file descriptor.
*
* Available flags are:
*
* * `poll_handle::event::READABLE`
* * `poll_handle::event::WRITABLE`
* * `poll_handle::event::DISCONNECT`
* * `poll_handle::event::PRIORITIZED`
*
* As soon as an event is detected, a poll event is emitted by the
* handle.
*
* Calling more than once this method will update the flags to which the
* caller is interested.
*
* @param flags The events to which the caller is interested.
* @return Underlying return value.
*/
int start(poll_event_flags flags);
/**
* @brief Stops polling the file descriptor.
* @return Underlying return value.
*/
int stop();
private:
enum {
FD,
SOCKET
} tag;
union {
int file_desc;
os_socket_handle socket;
};
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "poll.ipp"
#endif
#endif // UVW_POLL_INCLUDE_H

View File

@ -1,155 +0,0 @@
#pragma once
#include <type_traits>
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "util.hpp"
namespace uvw {
namespace details {
enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT
};
}
/**
* @brief PollEvent event.
*
* It will be emitted by PollHandle according with its functionalities.
*/
struct PollEvent {
explicit PollEvent(Flags<details::UVPollEvent> events) noexcept
: flags{std::move(events)}
{}
/**
* @brief Detected events all in one.
*
* Available flags are:
*
* * `PollHandle::Event::READABLE`
* * `PollHandle::Event::WRITABLE`
* * `PollHandle::Event::DISCONNECT`
*/
Flags<details::UVPollEvent> flags;
};
/**
* @brief The PollHandle handle.
*
* Poll handles are used to watch file descriptors for readability, writability
* and disconnection.
*
* To create a `PollHandle` through a `Loop`, arguments follow:
*
* * A descriptor that can be:
* * either an `int` file descriptor
* * or a `OSSocketHandle` socket descriptor
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/poll.html)
* for further details.
*/
class PollHandle final: public Handle<PollHandle, uv_poll_t> {
static void startCallback(uv_poll_t *handle, int status, int events) {
PollHandle &poll = *(static_cast<PollHandle*>(handle->data));
if(status) { poll.publish(ErrorEvent{status}); }
else { poll.publish(PollEvent{static_cast<std::underlying_type_t<Event>>(events)}); }
}
public:
using Event = details::UVPollEvent;
explicit PollHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, int desc)
: Handle{std::move(ca), std::move(ref)}, tag{FD}, fd{desc}
{}
explicit PollHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, OSSocketHandle sock)
: Handle{std::move(ca), std::move(ref)}, tag{SOCKET}, socket{sock}
{}
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return (tag == SOCKET)
? initialize(&uv_poll_init_socket, socket)
: initialize(&uv_poll_init, fd);
}
/**
* @brief Starts polling the file descriptor.
*
* Available flags are:
*
* * `PollHandle::Event::READABLE`
* * `PollHandle::Event::WRITABLE`
* * `PollHandle::Event::DISCONNECT`
*
* As soon as an event is detected, a PollEvent is emitted by the
* handle.<br>
* It could happen that ErrorEvent events are emitted while running.
*
* Calling more than once this method will update the flags to which the
* caller is interested.
*
* @param flags The events to which the caller is interested.
*/
void start(Flags<Event> flags) {
invoke(&uv_poll_start, get(), flags, &startCallback);
}
/**
* @brief Starts polling the file descriptor.
*
* Available flags are:
*
* * `PollHandle::Event::READABLE`
* * `PollHandle::Event::WRITABLE`
* * `PollHandle::Event::DISCONNECT`
*
* As soon as an event is detected, a PollEvent is emitted by the
* handle.<br>
* It could happen that ErrorEvent events are emitted while running.
*
* Calling more than once this method will update the flags to which the
* caller is interested.
*
* @param event The event to which the caller is interested.
*/
void start(Event event) {
start(Flags<Event>{event});
}
/**
* @brief Stops polling the file descriptor.
*/
void stop() {
invoke(&uv_poll_stop, get());
}
private:
enum { FD, SOCKET } tag;
union {
int fd;
OSSocketHandle::Type socket;
};
};
}

40
src/uvw/poll.ipp Normal file
View File

@ -0,0 +1,40 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE poll_event::poll_event(details::uvw_poll_event events) noexcept
: flags{events} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, int desc)
: handle{token, std::move(ref)}, tag{FD}, file_desc{desc} {}
UVW_INLINE poll_handle::poll_handle(loop::token token, std::shared_ptr<loop> ref, os_socket_handle sock)
: handle{token, std::move(ref)}, tag{SOCKET}, socket{sock} {}
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
UVW_INLINE void poll_handle::start_callback(uv_poll_t *hndl, int status, int events) {
if(poll_handle &poll = *(static_cast<poll_handle *>(hndl->data)); status) {
poll.publish(error_event{status});
} else {
poll.publish(poll_event{poll_event_flags(events)});
}
}
UVW_INLINE int poll_handle::init() {
if(tag == SOCKET) {
return leak_if(uv_poll_init_socket(parent().raw(), raw(), socket));
} else {
return leak_if(uv_poll_init(parent().raw(), raw(), file_desc));
}
}
UVW_INLINE int poll_handle::start(poll_event_flags flags) {
return uv_poll_start(raw(), static_cast<uv_poll_event>(flags), &start_callback);
}
UVW_INLINE int poll_handle::stop() {
return uv_poll_stop(raw());
}
} // namespace uvw

2
src/uvw/prepare.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "prepare.h"
#include "prepare.ipp"

58
src/uvw/prepare.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef UVW_PREPARE_INCLUDE_H
#define UVW_PREPARE_INCLUDE_H
#include <uv.h>
#include "handle.hpp"
#include "loop.h"
namespace uvw {
/*! @brief Prepare event. */
struct prepare_event {};
/**
* @brief The prepare handle.
*
* Prepare handles will emit a prepare event once per loop iteration, right
* before polling for I/O.
*
* To create a `prepare_handle` through a `loop`, no arguments are required.
*/
class prepare_handle final: public handle<prepare_handle, uv_prepare_t, prepare_event> {
static void start_callback(uv_prepare_t *hndl);
public:
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts the handle.
*
* A prepare event will be emitted once per loop iteration, right before
* polling for I/O.
*
* The handle will start emitting prepare events when needed.
*
* @return Underlying return value.
*/
int start();
/**
* @brief Stops the handle.
* @return Underlying return value.
*/
int stop();
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "prepare.ipp"
#endif
#endif // UVW_PREPARE_INCLUDE_H

View File

@ -1,68 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief PrepareEvent event.
*
* It will be emitted by PrepareHandle according with its functionalities.
*
* To create a `PrepareHandle` through a `Loop`, no arguments are required.
*/
struct PrepareEvent {};
/**
* @brief The PrepareHandle handle.
*
* Prepare handles will emit a PrepareEvent event once per loop iteration, right
* before polling for I/O.
*/
class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
static void startCallback(uv_prepare_t *handle) {
PrepareHandle &prepare = *(static_cast<PrepareHandle*>(handle->data));
prepare.publish(PrepareEvent{});
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_prepare_init);
}
/**
* @brief Starts the handle.
*
* A PrepareEvent event will be emitted once per loop iteration, right
* before polling for I/O.
*
* The handle will start emitting PrepareEvent when needed.
*/
void start() {
invoke(&uv_prepare_start, get(), &startCallback);
}
/**
* @brief Stops the handle.
*/
void stop() {
invoke(&uv_prepare_stop, get());
}
};
}

22
src/uvw/prepare.ipp Normal file
View File

@ -0,0 +1,22 @@
#include "config.h"
namespace uvw {
UVW_INLINE void prepare_handle::start_callback(uv_prepare_t *hndl) {
prepare_handle &prepare = *(static_cast<prepare_handle *>(hndl->data));
prepare.publish(prepare_event{});
}
UVW_INLINE int prepare_handle::init() {
return leak_if(uv_prepare_init(parent().raw(), raw()));
}
UVW_INLINE int prepare_handle::start() {
return uv_prepare_start(raw(), &start_callback);
}
UVW_INLINE int prepare_handle::stop() {
return uv_prepare_stop(raw());
}
} // namespace uvw

2
src/uvw/process.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "process.h"
#include "process.ipp"

245
src/uvw/process.h Normal file
View File

@ -0,0 +1,245 @@
#ifndef UVW_PROCESS_INCLUDE_H
#define UVW_PROCESS_INCLUDE_H
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <uv.h>
#include "config.h"
#include "enum.hpp"
#include "handle.hpp"
#include "loop.h"
#include "stream.h"
#include "util.h"
namespace uvw {
namespace details {
enum class uvw_process_flags : std::underlying_type_t<uv_process_flags> {
SETUID = UV_PROCESS_SETUID,
SETGID = UV_PROCESS_SETGID,
WINDOWS_VERBATIM_ARGUMENTS = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
DETACHED = UV_PROCESS_DETACHED,
WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE,
WINDOWS_HIDE_CONSOLE = UV_PROCESS_WINDOWS_HIDE_CONSOLE,
WINDOWS_HIDE_GUI = UV_PROCESS_WINDOWS_HIDE_GUI,
WINDOWS_FILE_PATH_EXACT_NAME = UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME,
UVW_ENUM = 0
};
enum class uvw_stdio_flags : std::underlying_type_t<uv_stdio_flags> {
IGNORE_STREAM = UV_IGNORE,
CREATE_PIPE = UV_CREATE_PIPE,
INHERIT_FD = UV_INHERIT_FD,
INHERIT_STREAM = UV_INHERIT_STREAM,
READABLE_PIPE = UV_READABLE_PIPE,
WRITABLE_PIPE = UV_WRITABLE_PIPE,
OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE,
UVW_ENUM = 0
};
} // namespace details
/*! @brief Exit event. */
struct exit_event {
explicit exit_event(int64_t code, int sig) noexcept;
int64_t status; /*!< The exit status. */
int signal; /*!< The signal that caused the process to terminate, if any. */
};
/**
* @brief The process handle.
*
* Process handles will spawn a new process and allow the user to control it and
* establish communication channels with it using streams.
*/
class process_handle final: public handle<process_handle, uv_process_t, exit_event> {
static void exit_callback(uv_process_t *hndl, int64_t exit_status, int term_signal);
public:
using process_flags = details::uvw_process_flags;
using stdio_flags = details::uvw_stdio_flags;
process_handle(loop::token token, std::shared_ptr<loop> ref);
/**
* @brief Disables inheritance for file descriptors/handles.
*
* Disables inheritance for file descriptors/handles that this process
* inherited from its parent. The effect is that child processes spawned by
* this process dont accidentally inherit these handles.<br/>
* It is recommended to call this function as early in your program as
* possible, before the inherited file descriptors can be closed or
* duplicated.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_disable_stdio_inheritance)
* for further details.
*/
static void disable_stdio_inheritance() noexcept;
/**
* @brief kill Sends the specified signal to the given PID.
* @param pid A valid process id.
* @param signum A valid signal identifier.
* @return True in case of success, false otherwise.
*/
static bool kill(int pid, int signum) noexcept;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief spawn Starts the process.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html)
* for further details.
*
* @param file Path pointing to the program to be executed.
* @param args Command line arguments.
* @param env Optional environment for the new process.
* @return Underlying return value.
*/
int spawn(const char *file, char **args, char **env = nullptr);
/**
* @brief Sends the specified signal to the internal process handle.
* @param signum A valid signal identifier.
* @return Underlying return value.
*/
int kill(int signum);
/**
* @brief Gets the PID of the spawned process.
*
* Its set after calling `spawn()`.
*
* @return The PID of the spawned process.
*/
int pid() noexcept;
/**
* @brief Sets the current working directory for the subprocess.
* @param path The working directory to be used when `spawn()` is invoked.
* @return A reference to this process handle.
*/
process_handle &cwd(const std::string &path) noexcept;
/**
* @brief Sets flags that control how `spawn()` behaves.
*
* Available flags are:
*
* * `process_handle::process_flags::SETUID`
* * `process_handle::process_flags::SETGID`
* * `process_handle::process_flags::WINDOWS_VERBATIM_ARGUMENTS`
* * `process_handle::process_flags::DETACHED`
* * `process_handle::process_flags::WINDOWS_HIDE`
* * `process_handle::process_flags::WINDOWS_HIDE_CONSOLE`
* * `process_handle::process_flags::WINDOWS_HIDE_GUI`
* * `process_handle::process_flags::WINDOWS_FILE_PATH_EXACT_NAME`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_process_flags)
* for further details.
*
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
process_handle &flags(process_flags flags) noexcept;
/**
* @brief Makes a `stdio` handle available to the child process.
*
* Available flags are:
*
* * `process_handle::stdio_flags::IGNORE_STREAM`
* * `process_handle::stdio_flags::CREATE_PIPE`
* * `process_handle::stdio_flags::INHERIT_FD`
* * `process_handle::stdio_flags::INHERIT_STREAM`
* * `process_handle::stdio_flags::READABLE_PIPE`
* * `process_handle::stdio_flags::WRITABLE_PIPE`
* * `process_handle::stdio_flags::OVERLAPPED_PIPE`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags)
* for further details.
*
* @param stream A valid `stdio` handle.
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
template<typename T, typename U, typename... E>
process_handle &stdio(stream_handle<T, U, E...> &stream, stdio_flags flags) {
uv_stdio_container_t container;
container.flags = static_cast<uv_stdio_flags>(flags);
container.data.stream = reinterpret_cast<uv_stream_t *>(stream.raw());
po_stream_stdio.push_back(container);
return *this;
}
/**
* @brief Makes a file descriptor available to the child process.
*
* Available flags are:
*
* * `process_handle::stdio_flags::IGNORE_STREAM`
* * `process_handle::stdio_flags::CREATE_PIPE`
* * `process_handle::stdio_flags::INHERIT_FD`
* * `process_handle::stdio_flags::INHERIT_STREAM`
* * `process_handle::stdio_flags::READABLE_PIPE`
* * `process_handle::stdio_flags::WRITABLE_PIPE`
* * `process_handle::stdio_flags::OVERLAPPED_PIPE`
*
* Default file descriptors are:
* * `uvw::std_in` for `stdin`
* * `uvw::std_out` for `stdout`
* * `uvw::std_err` for `stderr`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags)
* for further details.
*
* @param fd A valid file descriptor.
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
process_handle &stdio(file_handle fd, stdio_flags flags);
/**
* @brief Sets the child process' user id.
* @param id A valid user id to be used.
* @return A reference to this process handle.
*/
process_handle &uid(uid_type id);
/**
* @brief Sets the child process' group id.
* @param id A valid group id to be used.
* @return A reference to this process handle.
*/
process_handle &gid(gid_type id);
private:
std::string po_cwd;
process_flags po_flags;
std::vector<uv_stdio_container_t> po_fd_stdio;
std::vector<uv_stdio_container_t> po_stream_stdio;
uid_type po_uid;
gid_type po_gid;
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "process.ipp"
#endif
#endif // UVW_PROCESS_INCLUDE_H

View File

@ -1,324 +0,0 @@
#pragma once
#include <algorithm>
#include <utility>
#include <memory>
#include <string>
#include <vector>
#include <uv.h>
#include "handle.hpp"
#include "stream.hpp"
#include "util.hpp"
#include "loop.hpp"
namespace uvw {
namespace details {
enum class UVProcessFlags: std::underlying_type_t<uv_process_flags> {
SETUID = UV_PROCESS_SETUID,
SETGID = UV_PROCESS_SETGID,
WINDOWS_VERBATIM_ARGUMENTS = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
DETACHED = UV_PROCESS_DETACHED,
WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE
};
enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
IGNORE_STREAM = UV_IGNORE,
CREATE_PIPE = UV_CREATE_PIPE,
INHERIT_FD = UV_INHERIT_FD,
INHERIT_STREAM = UV_INHERIT_STREAM,
READABLE_PIPE = UV_READABLE_PIPE,
WRITABLE_PIPE = UV_WRITABLE_PIPE
};
}
/**
* @brief ExitEvent event.
*
* It will be emitted by ProcessHandle according with its functionalities.
*/
struct ExitEvent {
explicit ExitEvent(int64_t code, int sig) noexcept
: status{code}, signal{sig}
{}
int64_t status; /*!< The exit status. */
int signal; /*!< The signal that caused the process to terminate, if any. */
};
/**
* @brief The ProcessHandle handle.
*
* Process handles will spawn a new process and allow the user to control it and
* establish communication channels with it using streams.
*/
class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal) {
ProcessHandle &process = *(static_cast<ProcessHandle*>(handle->data));
process.publish(ExitEvent{exitStatus, termSignal});
}
public:
using Process = details::UVProcessFlags;
using StdIO = details::UVStdIOFlags;
ProcessHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
: Handle{std::move(ca), std::move(ref)}, poFdStdio{1}
{
// stdin container default initialization
poFdStdio[0].flags = static_cast<uv_stdio_flags>(StdIO::IGNORE_STREAM);
}
/**
* @brief Disables inheritance for file descriptors/handles.
*
* Disables inheritance for file descriptors/handles that this process
* inherited from its parent. The effect is that child processes spawned by
* this process dont accidentally inherit these handles.<br/>
* It is recommended to call this function as early in your program as
* possible, before the inherited file descriptors can be closed or
* duplicated.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_disable_stdio_inheritance)
* for further details.
*/
static void disableStdIOInheritance() noexcept {
uv_disable_stdio_inheritance();
}
/**
* @brief kill Sends the specified signal to the given PID.
* @param pid A valid process id.
* @param signum A valid signal identifier.
* @return True in case of success, false otherwise.
*/
static bool kill(int pid, int signum) noexcept {
return (0 == uv_kill(pid, signum));
}
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
// fake initialization so as to have leak invoked
return initialize([](auto...){ return 0; });
}
/**
* @brief spawn Starts the process.
*
* If the process isn't successfully spawned, an ErrorEvent event will be
* emitted by the handle.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html)
* for further details.
*
* @param file Path pointing to the program to be executed.
* @param args Command line arguments.
* @param env Optional environment for the new process.
*/
void spawn(const char *file, char **args, char **env = nullptr) {
uv_process_options_t po;
po.exit_cb = &exitCallback;
po.file = file;
po.args = args;
po.env = env;
po.cwd = poCwd.empty() ? nullptr : poCwd.data();
po.flags = poFlags;
po.uid = poUid;
po.gid = poGid;
/**
* See the constructor, poFdStdio[0] is stdin. It must be poStdio[0] by
* convention. From the official documentation:
*
* > The convention is that stdio[0] points to stdin, fd 1 is used
* > for stdout, and fd 2 is stderr.
*/
std::vector<uv_stdio_container_t> poStdio{poFdStdio.size() + poStreamStdio.size()};
poStdio.insert(poStdio.begin(), poStreamStdio.cbegin(), poStreamStdio.cend());
poStdio.insert(poStdio.begin(), poFdStdio.cbegin(), poFdStdio.cend());
po.stdio_count = static_cast<decltype(po.stdio_count)>(poStdio.size());
po.stdio = poStdio.data();
invoke(&uv_spawn, parent(), get(), &po);
}
/**
* @brief Sends the specified signal to the internal process handle.
* @param signum A valid signal identifier.
*/
void kill(int signum) {
invoke(&uv_process_kill, get(), signum);
}
/**
* @brief Gets the PID of the spawned process.
*
* Its set after calling `spawn()`.
*
* @return The PID of the spawned process.
*/
int pid() noexcept {
return get()->pid;
}
/**
* @brief Sets the current working directory for the subprocess.
* @param path The working directory to be used when `spawn()` is invoked.
* @return A reference to this process handle.
*/
ProcessHandle& cwd(std::string &path) noexcept {
poCwd = path;
return *this;
}
/**
* @brief Sets flags that control how `spawn()` behaves.
*
* Available flags are:
*
* * `ProcessHandle::Process::SETUID`
* * `ProcessHandle::Process::SETGID`
* * `ProcessHandle::Process::WINDOWS_VERBATIM_ARGUMENTS`
* * `ProcessHandle::Process::DETACHED`
* * `ProcessHandle::Process::WINDOWS_HIDE`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_process_flags)
* for further details.
*
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
ProcessHandle& flags(Flags<Process> flags) noexcept {
poFlags = flags;
return *this;
}
/**
* @brief Makes a `stdio` handle available to the child process.
*
* Available flags are:
*
* * `ProcessHandle::StdIO::IGNORE_STREAM`
* * `ProcessHandle::StdIO::CREATE_PIPE`
* * `ProcessHandle::StdIO::INHERIT_FD`
* * `ProcessHandle::StdIO::INHERIT_STREAM`
* * `ProcessHandle::StdIO::READABLE_PIPE`
* * `ProcessHandle::StdIO::WRITABLE_PIPE`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags)
* for further details.
*
* @param stream A valid `stdio` handle.
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
template<typename T, typename U>
ProcessHandle& stdio(StreamHandle<T, U> &stream, Flags<StdIO> flags) {
uv_stdio_container_t container;
Flags<StdIO>::Type fgs = flags;
container.flags = static_cast<uv_stdio_flags>(fgs);
container.data.stream = get<uv_stream_t>(stream);
poStreamStdio.push_back(std::move(container));
return *this;
}
/**
* @brief Makes a file descriptor available to the child process.
*
* Available flags are:
*
* * `ProcessHandle::StdIO::IGNORE_STREAM`
* * `ProcessHandle::StdIO::CREATE_PIPE`
* * `ProcessHandle::StdIO::INHERIT_FD`
* * `ProcessHandle::StdIO::INHERIT_STREAM`
* * `ProcessHandle::StdIO::READABLE_PIPE`
* * `ProcessHandle::StdIO::WRITABLE_PIPE`
*
* Default file descriptors are:
* * `uvw::StdIN` for `stdin`
* * `uvw::StdOUT` for `stdout`
* * `uvw::StdERR` for `stderr`
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags)
* for further details.
*
* @param fd A valid file descriptor.
* @param flags A valid set of flags.
* @return A reference to this process handle.
*/
ProcessHandle& stdio(FileHandle fd, Flags<StdIO> flags) {
auto fgs = static_cast<uv_stdio_flags>(Flags<StdIO>::Type{flags});
auto actual = FileHandle::Type{fd};
if(actual == FileHandle::Type{StdIN}) {
poFdStdio[0].flags = fgs;
} else {
auto it = std::find_if(poFdStdio.begin(), poFdStdio.end(), [actual](auto &&container){
return container.data.fd == actual;
});
if(it == poFdStdio.cend()) {
uv_stdio_container_t container;
container.flags = fgs;
container.data.fd = actual;
poFdStdio.push_back(std::move(container));
} else {
it->flags = fgs;
it->data.fd = actual;
}
}
return *this;
}
/**
* @brief Sets the child process' user id.
* @param id A valid user id to be used.
* @return A reference to this process handle.
*/
ProcessHandle& uid(Uid id) {
poUid = id;
return *this;
}
/**
* @brief Sets the child process' group id.
* @param id A valid group id to be used.
* @return A reference to this process handle.
*/
ProcessHandle& gid(Gid id) {
poGid = id;
return *this;
}
private:
std::string poCwd;
Flags<Process> poFlags;
std::vector<uv_stdio_container_t> poFdStdio;
std::vector<uv_stdio_container_t> poStreamStdio;
Uid poUid;
Gid poGid;
};
}

107
src/uvw/process.ipp Normal file
View File

@ -0,0 +1,107 @@
#include <algorithm>
#include "config.h"
namespace uvw {
UVW_INLINE exit_event::exit_event(int64_t code, int sig) noexcept
: status{code}, signal{sig} {}
UVW_INLINE void process_handle::exit_callback(uv_process_t *hndl, int64_t exit_status, int term_signal) {
process_handle &process = *(static_cast<process_handle *>(hndl->data));
process.publish(exit_event{exit_status, term_signal});
}
UVW_INLINE process_handle::process_handle(loop::token token, std::shared_ptr<loop> ref)
: handle{token, std::move(ref)} {}
UVW_INLINE void process_handle::disable_stdio_inheritance() noexcept {
uv_disable_stdio_inheritance();
}
UVW_INLINE bool process_handle::kill(int pid, int signum) noexcept {
return (0 == uv_kill(pid, signum));
}
UVW_INLINE int process_handle::init() {
// deferred initialization: libuv initializes process handles only when
// uv_spawn is invoked and uvw stays true to the underlying library
return 0;
}
UVW_INLINE int process_handle::spawn(const char *file, char **args, char **env) {
uv_process_options_t po;
po.exit_cb = &exit_callback;
po.file = file;
po.args = args;
po.env = env;
po.cwd = po_cwd.empty() ? nullptr : po_cwd.data();
po.flags = static_cast<uv_process_flags>(po_flags);
po.uid = po_uid;
po.gid = po_gid;
std::vector<uv_stdio_container_t> poStdio;
poStdio.reserve(po_fd_stdio.size() + po_stream_stdio.size());
poStdio.insert(poStdio.begin(), po_fd_stdio.cbegin(), po_fd_stdio.cend());
poStdio.insert(poStdio.end(), po_stream_stdio.cbegin(), po_stream_stdio.cend());
po.stdio_count = static_cast<decltype(po.stdio_count)>(poStdio.size());
po.stdio = poStdio.data();
// see init member function for more details
static_cast<void>(leak_if(0));
return uv_spawn(parent().raw(), raw(), &po);
}
UVW_INLINE int process_handle::kill(int signum) {
return uv_process_kill(raw(), signum);
}
UVW_INLINE int process_handle::pid() noexcept {
return raw()->pid;
}
UVW_INLINE process_handle &process_handle::cwd(const std::string &path) noexcept {
po_cwd = path;
return *this;
}
UVW_INLINE process_handle &process_handle::flags(process_flags flags) noexcept {
po_flags = flags;
return *this;
}
UVW_INLINE process_handle &process_handle::stdio(file_handle fd, stdio_flags flags) {
auto fgs = static_cast<uv_stdio_flags>(flags);
auto actual = uvw::file_handle{fd};
auto it = std::find_if(po_fd_stdio.begin(), po_fd_stdio.end(), [actual](auto &&container) {
return static_cast<const uvw::details::uv_type_wrapper<int>>(container.data.fd) == static_cast<const uvw::details::uv_type_wrapper<int>>(actual);
});
if(it == po_fd_stdio.cend()) {
uv_stdio_container_t container;
container.flags = fgs;
container.data.fd = actual;
po_fd_stdio.push_back(container);
} else {
it->flags = fgs;
it->data.fd = actual;
}
return *this;
}
UVW_INLINE process_handle &process_handle::uid(uid_type id) {
po_uid = id;
return *this;
}
UVW_INLINE process_handle &process_handle::gid(gid_type id) {
po_gid = id;
return *this;
}
} // namespace uvw

View File

@ -1,76 +1,57 @@
#pragma once
#ifndef UVW_REQUEST_INCLUDE_H
#define UVW_REQUEST_INCLUDE_H
#include <memory>
#include <type_traits>
#include <utility>
#include <memory>
#include <uv.h>
#include "config.h"
#include "resource.hpp"
namespace uvw {
template<typename T, typename U>
class Request: public Resource<T, U> {
/**
* @brief Request base class.
*
* Base type for all `uvw` request types.
*/
template<typename T, typename U, typename... E>
class request: public resource<T, U, E...> {
protected:
static auto reserve(U *req) {
auto ptr = static_cast<T*>(req->data)->shared_from_this();
ptr->reset();
[[nodiscard]] static auto reserve(U *req) {
auto ptr = static_cast<T *>(req->data)->shared_from_this();
ptr->self_reset();
return ptr;
}
template<typename E>
static void defaultCallback(U *req, int status) {
auto ptr = reserve(req);
if(status) { ptr->publish(ErrorEvent{status}); }
else { ptr->publish(E{}); }
}
template<typename F, typename... Args>
auto invoke(F &&f, Args&&... args)
-> std::enable_if_t<not std::is_void<std::result_of_t<F(Args...)>>::value, int> {
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
else { this->leak(); }
return err;
}
template<typename F, typename... Args>
auto invoke(F &&f, Args&&... args)
-> std::enable_if_t<std::is_void<std::result_of_t<F(Args...)>>::value> {
std::forward<F>(f)(std::forward<Args>(args)...);
this->leak();
}
public:
using Resource<T, U>::Resource;
using resource<T, U, E...>::resource;
/**
* @brief Cancels a pending request.
*
* This method fails if the request is executing or has finished
* executing.<br/>
* It can emit an ErrorEvent event in case of errors.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/request.html#c.uv_cancel)
* for further details.
*
* @return True in case of success, false otherwise.
*/
bool cancel() {
return (0 == uv_cancel(this->template get<uv_req_t>()));
* @brief Cancels a pending request.
*
* This method fails if the request is executing or has finished
* executing.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/request.html#c.uv_cancel)
* for further details.
*
* @return Underlying return value.
*/
int cancel() {
return uv_cancel(reinterpret_cast<uv_req_t *>(this->raw()));
}
/**
* @brief Returns the size of the underlying request type.
* @return The size of the underlying request type.
*/
std::size_t size() const noexcept {
return uv_req_size(this->template get<uv_req_t>()->type);
* @brief Returns the size of the underlying request type.
* @return The size of the underlying request type.
*/
[[nodiscard]] std::size_t size() const noexcept {
return uv_req_size(reinterpret_cast<const uv_req_t *>(this->raw())->type);
}
};
} // namespace uvw
}
#endif // UVW_REQUEST_INCLUDE_H

View File

@ -1,135 +1,66 @@
#pragma once
#ifndef UVW_RESOURCE_INCLUDE_H
#define UVW_RESOURCE_INCLUDE_H
#include <utility>
#include <memory>
#include <uv.h>
#include "emitter.hpp"
#include "loop.hpp"
#include <utility>
#include "config.h"
#include "emitter.h"
#include "uv_type.hpp"
namespace uvw {
/**
* @brief Common class for almost all the resources available in `uvw`.
*
* This is the base class for handles and requests.<br/>
* It mainly acts as a wrapper around a data structure of `libuv`.
* This is the base class for handles and requests.
*/
template<typename T, typename U>
class Resource: public Emitter<T>, public std::enable_shared_from_this<T> {
template<typename, typename>
friend class Resource;
template<typename T, typename U, typename... E>
class resource: public uv_type<U>, public emitter<T, E...>, public std::enable_shared_from_this<T> {
protected:
struct ConstructorAccess { explicit ConstructorAccess(int) {} };
[[nodiscard]] int leak_if(int err) noexcept {
if(err == 0) {
self_ptr = this->shared_from_this();
}
auto parent() const noexcept {
return pLoop->loop.get();
return err;
}
auto get() noexcept {
return &resource;
void self_reset() noexcept {
self_ptr.reset();
}
auto get() const noexcept {
return const_cast<const U *>(&resource);
}
template<typename R>
auto get() noexcept {
static_assert(not std::is_same<R, U>::value, "!");
return reinterpret_cast<R *>(&resource);
}
template<typename R, typename... P>
auto get(Resource<P...> &res) noexcept {
return reinterpret_cast<R *>(&res.resource);
}
template<typename R>
auto get() const noexcept {
static_assert(not std::is_same<R, U>::value, "!");
return reinterpret_cast<const R *>(&resource);
}
template<typename R, typename... P>
auto get(const Resource<P...> &res) const noexcept {
return reinterpret_cast<const R *>(&res.resource);
}
void leak() noexcept {
sPtr = this->shared_from_this();
}
void reset() noexcept {
sPtr.reset();
}
bool self() const noexcept {
return static_cast<bool>(sPtr);
[[nodiscard]] bool has_self() const noexcept {
return static_cast<bool>(self_ptr);
}
public:
explicit Resource(ConstructorAccess, std::shared_ptr<Loop> ref)
: Emitter<T>{},
std::enable_shared_from_this<T>{},
pLoop{std::move(ref)},
resource{}
{
resource.data = static_cast<T*>(this);
explicit resource(loop::token token, std::shared_ptr<loop> ref)
: uv_type<U>{token, std::move(ref)} {
this->raw()->data = this;
}
Resource(const Resource &) = delete;
Resource(Resource &&) = delete;
virtual ~Resource() {
static_assert(std::is_base_of<Resource<T, U>, T>::value, "!");
}
Resource& operator=(const Resource &) = delete;
Resource& operator=(Resource &&) = delete;
/**
* @brief Creates a new resource of the given type.
* @param args Arguments to be forwarded to the actual constructor (if any).
* @return A pointer to the newly created resource.
*/
template<typename... Args>
static std::shared_ptr<T> create(Args&&... args) {
return std::make_shared<T>(ConstructorAccess{0}, std::forward<Args>(args)...);
}
/**
* @brief Gets the loop from which the resource was originated.
* @return A reference to a loop instance.
*/
Loop& loop() const noexcept { return *pLoop; }
/**
* @brief Gets user-defined data. `uvw` won't use this field in any case.
* @return User-defined data if any, an invalid pointer otherwise.
*/
template<typename R = void>
std::shared_ptr<R> data() const {
return std::static_pointer_cast<R>(userData);
[[nodiscard]] std::shared_ptr<R> data() const {
return std::static_pointer_cast<R>(user_data);
}
/**
* @brief Sets arbitrary data. `uvw` won't use this field in any case.
* @param uData User-defined arbitrary data.
* @param udata User-defined arbitrary data.
*/
void data(std::shared_ptr<void> uData) {
userData = std::move(uData);
void data(std::shared_ptr<void> udata) {
user_data = std::move(udata);
}
private:
std::shared_ptr<void> userData{nullptr};
std::shared_ptr<void> sPtr{nullptr};
std::shared_ptr<Loop> pLoop;
U resource;
std::shared_ptr<void> user_data{nullptr};
std::shared_ptr<void> self_ptr{nullptr};
};
} // namespace uvw
}
#endif // UVW_RESOURCE_INCLUDE_H

2
src/uvw/signal.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "signal.h"
#include "signal.ipp"

83
src/uvw/signal.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef UVW_SIGNAL_INCLUDE_H
#define UVW_SIGNAL_INCLUDE_H
#include <uv.h>
#include "config.h"
#include "handle.hpp"
#include "loop.h"
namespace uvw {
/*! @brief Signal event. */
struct signal_event {
explicit signal_event(int sig) noexcept;
int signum; /*!< The signal being monitored by this handle. */
};
/**
* @brief The signal handle.
*
* Signal handles implement Unix style signal handling on a per-event loop
* bases.<br/>
* Reception of some signals is emulated on Windows.
*
* To create a `signal_handle` through a `loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/signal.html)
* for further details.
*/
class signal_handle final: public handle<signal_handle, uv_signal_t, signal_event> {
static void start_callback(uv_signal_t *hndl, int signum);
public:
using handle::handle;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
int init();
/**
* @brief Starts the handle.
*
* The handle will start emitting signal events when needed.
*
* @param signum The signal to be monitored.
* @return Underlying return value.
*/
int start(int signum);
/**
* @brief Starts the handle.
*
* Same functionality as signal_handle::start but the signal handler is
* reset the moment the signal is received.
*
* @param signum The signal to be monitored.
* @return Underlying return value.
*/
int one_shot(int signum);
/**
* @brief Stops the handle.
* @return Underlying return value.
*/
int stop();
/**
* @brief Gets the signal being monitored.
* @return The signal being monitored.
*/
int signal() const noexcept;
};
} // namespace uvw
#ifndef UVW_AS_LIB
# include "signal.ipp"
#endif
#endif // UVW_SIGNAL_INCLUDE_H

View File

@ -1,96 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "handle.hpp"
#include "loop.hpp"
namespace uvw {
/**
* @brief SignalEvent event.
*
* It will be emitted by SignalHandle according with its functionalities.
*/
struct SignalEvent {
explicit SignalEvent(int sig) noexcept: signum{sig} {}
int signum; /*!< The signal being monitored by this handle. */
};
/**
* @brief The SignalHandle handle.
*
* Signal handles implement Unix style signal handling on a per-event loop
* bases.<br/>
* Reception of some signals is emulated on Windows.
*
* To create a `SignalHandle` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/signal.html)
* for further details.
*/
class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
static void startCallback(uv_signal_t *handle, int signum) {
SignalHandle &signal = *(static_cast<SignalHandle*>(handle->data));
signal.publish(SignalEvent{signum});
}
public:
using Handle::Handle;
/**
* @brief Initializes the handle.
* @return True in case of success, false otherwise.
*/
bool init() {
return initialize(&uv_signal_init);
}
/**
* @brief Starts the handle.
*
* The handle will start emitting SignalEvent when needed.
*
* @param signum The signal to be monitored.
*/
void start(int signum) {
invoke(&uv_signal_start, get(), &startCallback, signum);
}
/**
* @brief Starts the handle.
*
* Same functionality as SignalHandle::start but the signal handler is reset
* the moment the signal is received.
*
* @param signum
*/
void oneShot(int signum) {
invoke(&uv_signal_start_oneshot, get(), &startCallback, signum);
}
/**
* @brief Stops the handle.
*/
void stop() {
invoke(&uv_signal_stop, get());
}
/**
* @brief Gets the signal being monitored.
* @return The signal being monitored.
*/
int signal() const noexcept {
return get()->signum;
}
};
}

33
src/uvw/signal.ipp Normal file
View File

@ -0,0 +1,33 @@
#include "config.h"
namespace uvw {
UVW_INLINE signal_event::signal_event(int sig) noexcept
: signum{sig} {}
UVW_INLINE void signal_handle::start_callback(uv_signal_t *hndl, int signum) {
signal_handle &signal = *(static_cast<signal_handle *>(hndl->data));
signal.publish(signal_event{signum});
}
UVW_INLINE int signal_handle::init() {
return leak_if(uv_signal_init(parent().raw(), raw()));
}
UVW_INLINE int signal_handle::start(int signum) {
return uv_signal_start(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::one_shot(int signum) {
return uv_signal_start_oneshot(raw(), &start_callback, signum);
}
UVW_INLINE int signal_handle::stop() {
return uv_signal_stop(raw());
}
UVW_INLINE int signal_handle::signal() const noexcept {
return raw()->signum;
}
} // namespace uvw

Some files were not shown because too many files have changed in this diff Show More