Compare commits

...

77 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
106 changed files with 3092 additions and 2701 deletions

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"

View File

@ -10,12 +10,12 @@ jobs:
strategy: strategy:
matrix: matrix:
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF] mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Compile tests - name: Compile tests
working-directory: build working-directory: build
run: | run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF .. cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j2 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

@ -16,23 +16,22 @@ jobs:
- { pkg: clang, exe: 'clang++', version: 9 } - { pkg: clang, exe: 'clang++', version: 9 }
- { pkg: clang, exe: 'clang++', version: 10 } - { pkg: clang, exe: 'clang++', version: 10 }
- { pkg: clang, exe: 'clang++', version: 11 } - { pkg: clang, exe: 'clang++', version: 11 }
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF] mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }} - name: Install ${{ matrix.compiler.exe }}
run: | run: |
sudo apt-get update --fix-missing sudo apt-get update --fix-missing
sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }} sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }}
- name: Compile tests - name: Compile tests
working-directory: build
env: env:
CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }} CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }}
run: | run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF .. cmake ${{ matrix.mode }} --preset ci-ubuntu
make -j2 cmake --build build/ --parallel 2
- name: Run tests - name: Run tests
working-directory: build working-directory: build
env: env:

View File

@ -15,23 +15,22 @@ jobs:
- { pkg: clang, exe: 'clang++', version: 12 } - { pkg: clang, exe: 'clang++', version: 12 }
- { pkg: clang, exe: 'clang++', version: 13 } - { pkg: clang, exe: 'clang++', version: 13 }
- { pkg: clang, exe: 'clang++', version: 14 } - { pkg: clang, exe: 'clang++', version: 14 }
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF] mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install ${{ matrix.compiler.exe }} - name: Install ${{ matrix.compiler.exe }}
run: | run: |
sudo apt-get update --fix-missing sudo apt-get update --fix-missing
sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }} sudo apt install -y ${{ matrix.compiler.pkg }}-${{ matrix.compiler.version }}
- name: Compile tests - name: Compile tests
working-directory: build
env: env:
CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }} CXX: ${{ matrix.compiler.exe }}-${{ matrix.compiler.version }}
run: | run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF .. cmake ${{ matrix.mode }} --preset ci-ubuntu
make -j2 cmake --build build/ --parallel 2
- name: Run tests - name: Run tests
working-directory: build working-directory: build
env: env:

View File

@ -11,12 +11,12 @@ jobs:
strategy: strategy:
matrix: matrix:
generator: [Visual Studio 17 2022] generator: [Visual Studio 17 2022]
mode: [-DBUILD_UVW_SHARED_LIB=ON, -DBUILD_UVW_LIBS=ON, -DBUILD_UVW_LIBS=OFF] mode: [-DUVW_BUILD_SHARED_LIB=ON, -DUVW_BUILD_LIBS=ON, -DUVW_BUILD_LIBS=OFF]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Compile tests - name: Compile tests
working-directory: build working-directory: build
run: | run: |
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF -DCMAKE_CXX_FLAGS=/W1 -G"${{ matrix.generator }}" .. 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 cmake --build . -j 2

View File

@ -9,14 +9,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Compile tests - name: Compile tests
working-directory: build working-directory: build
env: env:
CXXFLAGS: "-O0 --coverage -fno-inline -fno-inline-small-functions -fno-default-inline" CXXFLAGS: "-O0 --coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
CXX: g++ CXX: g++
run: | run: |
cmake -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF .. cmake -DUVW_BUILD_TESTING=ON -Dlibuv_buildtests=OFF ..
make -j4 make -j4
- name: Run tests - name: Run tests
working-directory: build working-directory: build

View File

@ -13,7 +13,7 @@ jobs:
steps: steps:
- uses: docker://conanio/gcc8 - uses: docker://conanio/gcc8
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Python - name: Setup Python
uses: actions/setup-python@master uses: actions/setup-python@master
with: with:

View File

@ -15,13 +15,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Compile tests - name: Compile tests
working-directory: build working-directory: build
env: env:
CXX: ${{ matrix.compiler }} CXX: ${{ matrix.compiler }}
run: | run: |
cmake ${{ matrix.mode }} -DBUILD_TESTING=ON -Dlibuv_buildtests=OFF -DUSE_${{ matrix.sanitizer }}=ON .. cmake ${{ matrix.mode }} -DUVW_BUILD_TESTING=ON -DUVW_USE_${{ matrix.sanitizer }}=ON -Dlibuv_buildtests=OFF ..
make -j2 make -j2
- name: Run tests - name: Run tests
working-directory: build working-directory: build

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

View File

@ -16,7 +16,7 @@ endif()
# Project configuration # Project configuration
# #
set(UVW_VERSION_MAJOR 3) set(UVW_VERSION_MAJOR 3)
set(UVW_VERSION_MINOR 2) set(UVW_VERSION_MINOR 5)
set(UVW_VERSION_PATCH 0) set(UVW_VERSION_PATCH 0)
project( project(
@ -31,22 +31,23 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug) set(CMAKE_BUILD_TYPE Debug)
endif() endif()
option(USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if availbale." ON) option(UVW_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." ON)
option(USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF) option(UVW_USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF)
option(USE_UBSAN "Use address sanitizer by adding -fsanitize=undefined -fno-sanitize-recover=all -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(BUILD_UVW_LIBS "Prepare targets for static library rather than for a header-only library." OFF) option(UVW_USE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF)
option(BUILD_UVW_SHARED_LIB "Prepare targets for shared library rather than for a header-only library." OFF) option(UVW_BUILD_LIBS "Prepare targets for static library rather than for a header-only library." OFF)
option(FIND_LIBUV "Try finding libuv library development files in the system" 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)
if(BUILD_UVW_SHARED_LIB) if(UVW_BUILD_SHARED_LIB)
set(BUILD_UVW_LIBS BOOL:ON) set(UVW_BUILD_LIBS BOOL:ON)
endif() endif()
# #
# Compiler stuff # Compiler stuff
# #
if(NOT WIN32 AND USE_LIBCPP) if(NOT WIN32 AND UVW_USE_LIBCPP)
include(CheckCXXSourceCompiles) include(CheckCXXSourceCompiles)
include(CMakePushCheckState) include(CMakePushCheckState)
@ -57,27 +58,34 @@ if(NOT WIN32 AND USE_LIBCPP)
check_cxx_source_compiles(" check_cxx_source_compiles("
#include<type_traits> #include<type_traits>
int main() { return std::is_same_v<int, char>; } int main() { return std::is_same_v<int, char>; }
" HAS_LIBCPP) " UVW_HAS_LIBCPP)
if(NOT HAS_LIBCPP) if(NOT UVW_HAS_LIBCPP)
message(WARNING "The option USE_LIBCPP is set (by default) but libc++ is not available. The flag will not be added to the target.") 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() endif()
cmake_pop_check_state() cmake_pop_check_state()
endif() 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 # Required minimal libuv version
set(LIBUV_VERSION 1.46.0) set(UVW_LIBUV_VERSION 1.49.0)
function(fetch_libuv) function(fetch_libuv)
if (FETCH_LIBUV) if (UVW_FETCH_LIBUV)
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
libuv libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG "v${LIBUV_VERSION}" GIT_TAG "v${UVW_LIBUV_VERSION}"
GIT_SHALLOW 1 GIT_SHALLOW 1
) )
@ -88,23 +96,24 @@ function(fetch_libuv)
add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL) add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
endif() endif()
if(BUILD_UVW_SHARED_LIB) if(UVW_BUILD_SHARED_LIB)
add_library(uv::uv-shared ALIAS uv) add_library(uv::uv-shared ALIAS uv)
set_target_properties(uv PROPERTIES POSITION_INDEPENDENT_CODE 1) set_target_properties(uv PROPERTIES POSITION_INDEPENDENT_CODE 1)
else() else()
add_library(uv::uv-static ALIAS uv_a) add_library(uv::uv-static ALIAS uv_a)
set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1) set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif() endif()
endif(FETCH_LIBUV) endif(UVW_FETCH_LIBUV)
endfunction() endfunction()
function(use_libuv) function(use_libuv)
set(FETCH_LIBUV_DEFAULT ON) set(UVW_FETCH_LIBUV_DEFAULT ON)
if (FIND_LIBUV)
if (UVW_FIND_LIBUV)
find_package(libuv ${LIBUV_VERSION} QUIET) find_package(libuv ${LIBUV_VERSION} QUIET)
if (libuv_FOUND) if (libuv_FOUND)
add_library(uv::uv-shared ALIAS uv) add_library(uv::uv-shared ALIAS uv)
set(FETCH_LIBUV_DEFAULT OFF) set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via cmake") message(STATUS "libuv ${libuv_VERSION} found via cmake")
else(libuv_FOUND) else(libuv_FOUND)
find_package(PkgConfig QUIET) find_package(PkgConfig QUIET)
@ -112,14 +121,15 @@ function(use_libuv)
pkg_check_modules(libuv IMPORTED_TARGET libuv>=${LIBUV_VERSION}) pkg_check_modules(libuv IMPORTED_TARGET libuv>=${LIBUV_VERSION})
if (libuv_FOUND) if (libuv_FOUND)
add_library(uv::uv-shared ALIAS PkgConfig::libuv) add_library(uv::uv-shared ALIAS PkgConfig::libuv)
set(FETCH_LIBUV_DEFAULT OFF) set(UVW_FETCH_LIBUV_DEFAULT OFF)
message(STATUS "libuv ${libuv_VERSION} found via pkg-config") message(STATUS "libuv ${libuv_VERSION} found via pkg-config")
endif(libuv_FOUND) endif(libuv_FOUND)
endif(PkgConfig_FOUND) endif(PkgConfig_FOUND)
endif(libuv_FOUND) endif(libuv_FOUND)
endif(FIND_LIBUV) endif(UVW_FIND_LIBUV)
option(UVW_FETCH_LIBUV "Fetch the libuv repo using CMake FetchContent facility" ${UVW_FETCH_LIBUV_DEFAULT})
option(FETCH_LIBUV "Fetch the libuv repo using CMake FetchContent facility" ${FETCH_LIBUV_DEFAULT})
fetch_libuv() fetch_libuv()
endfunction() endfunction()
@ -129,8 +139,7 @@ endfunction()
include(GNUInstallDirs) include(GNUInstallDirs)
if(UVW_BUILD_LIBS)
if(BUILD_UVW_LIBS)
use_libuv() use_libuv()
add_subdirectory(src) add_subdirectory(src)
@ -148,21 +157,25 @@ else()
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
if(USE_ASAN) if(UVW_USE_ASAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>) target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address>) target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=address>)
endif() endif()
if(USE_UBSAN) if(UVW_USE_UBSAN)
target_compile_options(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>) 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>) target_link_libraries(uvw INTERFACE $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif() endif()
if(HAS_LIBCPP) 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++) target_compile_options(uvw BEFORE INTERFACE -stdlib=libc++)
endif() endif()
file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp src/uvw/*.cpp) file(GLOB HEADERS src/uvw/*.h src/uvw/*.hpp)
endif() endif()
# #
@ -186,18 +199,21 @@ install(
# #
# Install targets # Install targets
# #
if (BUILD_UVW_LIBS)
if (UVW_BUILD_LIBS)
set_target_properties( set_target_properties(
uvw PROPERTIES uvw PROPERTIES
VERSION ${UVW_VERSION_MAJOR}.${UVW_VERSION_MINOR}.${UVW_VERSION_PATCH} VERSION ${UVW_VERSION_MAJOR}.${UVW_VERSION_MINOR}.${UVW_VERSION_PATCH}
SOVERSION ${UVW_VERSION_MAJOR} SOVERSION ${UVW_VERSION_MAJOR}
) )
endif() endif()
install( install(
EXPORT uvwConfig EXPORT uvwConfig
NAMESPACE uvw:: NAMESPACE uvw::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/uvw DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/uvw
) )
install( install(
TARGETS uvw TARGETS uvw
EXPORT uvwConfig EXPORT uvwConfig
@ -205,26 +221,27 @@ install(
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
) )
if(FETCH_LIBUV AND BUILD_UVW_LIBS)
if(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
# libuv is only fetched when both above conditions are true # libuv is only fetched when both above conditions are true
install(DIRECTORY ${libuv_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/uvw/uv/include) install(DIRECTORY ${libuv_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/uvw/uv/include)
if (BUILD_UVW_SHARED_LIB) if (UVW_BUILD_SHARED_LIB)
install(TARGETS uv EXPORT uvwConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw) install(TARGETS uv EXPORT uvwConfig LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
else() else()
install(TARGETS uv_a EXPORT uvwConfig ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw) install(TARGETS uv_a EXPORT uvwConfig ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/uvw)
endif() endif()
endif(UVW_FETCH_LIBUV AND UVW_BUILD_LIBS)
endif(FETCH_LIBUV AND BUILD_UVW_LIBS)
export(EXPORT uvwConfig) export(EXPORT uvwConfig)
### Testing ### Testing
option(BUILD_TESTING "Enable testing with ctest." OFF) option(UVW_BUILD_TESTING "Enable testing with ctest." OFF)
if(BUILD_TESTING) if(UVW_BUILD_TESTING)
option(FIND_GTEST_PACKAGE "Enable finding gtest package." OFF) option(UVW_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
if (NOT BUILD_UVW_LIBS) if (NOT UVW_BUILD_LIBS)
use_libuv() use_libuv()
endif() endif()
@ -236,32 +253,12 @@ endif()
# Documentation # Documentation
# #
option(BUILD_DOCS "Enable building with documentation." OFF) option(UVW_BUILD_DOCS "Enable building with documentation." OFF)
if(BUILD_DOCS) if(UVW_BUILD_DOCS)
find_package(Doxygen 1.8) find_package(Doxygen 1.10)
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
add_subdirectory(docs) add_subdirectory(docs)
endif() endif()
endif() endif()
#
# AOB
#
add_custom_target(
uvw_aob
SOURCES
.github/workflows/build-macos.yml
.github/workflows/build-ubuntu-20.04.yml
.github/workflows/build-ubuntu-latest.yml
.github/workflows/build-win.yml
.github/workflows/coverage.yml
.github/workflows/deploy.yml
.github/FUNDING.yml
AUTHORS
LICENSE
README.md
TODO
)

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) The MIT License (MIT)
Copyright (c) 2016-2023 Michele Caini Copyright (c) 2016-2024 Michele Caini
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,8 +1,5 @@
![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++](https://user-images.githubusercontent.com/1812216/46069406-c977a600-c17b-11e8-9a47-9bba6f412c57.png)
<!--
@cond TURN_OFF_DOXYGEN
-->
[![Build Status](https://github.com/skypjack/uvw/workflows/build/badge.svg)](https://github.com/skypjack/uvw/actions) [![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) [![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/) [![Documentation](https://img.shields.io/badge/docs-doxygen-blue)](https://skypjack.github.io/uvw/)
@ -18,9 +15,6 @@ If you use `uvw` and you want to say thanks or support the project, please
You can help me make the difference. You can help me make the difference.
[Many thanks](https://skypjack.github.io/sponsorship/) to those who supported me [Many thanks](https://skypjack.github.io/sponsorship/) to those who supported me
and still support me today. and still support me today.
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction # Introduction
@ -93,7 +87,8 @@ exist a valid `libuv` wrapper in C++. That's all.
To be able to use `uvw`, users must provide the following system-wide tools: To be able to use `uvw`, users must provide the following system-wide tools:
* A full-featured compiler that supports at least C++17. * A full-featured compiler that supports at least C++17.
* `libuv` (which version depends on the tag of `uvw` in use). * `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 The requirements below are mandatory to compile the tests and to extract the
documentation: documentation:
@ -106,6 +101,19 @@ 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` Because of that, users don't have to install it to run the tests or when `uvw`
libraries are compiled through `CMake`. 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 ## Library
`uvw` is a dual-mode library. It can be used in its header-only form or as a `uvw` is a dual-mode library. It can be used in its header-only form or as a
@ -132,7 +140,7 @@ When used through `CMake`, the `uvw::uvw` target is exported for convenience.
### Static ### Static
To use `uvw` as a compiled library, set the `BUILD_UVW_LIBS` options in cmake To use `uvw` as a compiled library, set the `UVW_BUILD_LIBS` options in cmake
before including the project.<br/> before including the project.<br/>
This option triggers the generation of a targets named This option triggers the generation of a targets named
`uvw::uvw-static`. The matching version of `libuv` is also `uvw::uvw-static`. The matching version of `libuv` is also
@ -201,7 +209,7 @@ else.
To build the tests: To build the tests:
* `$ cd build` * `$ cd build`
* `$ cmake .. -DBUILD_TESTING=ON` * `$ cmake .. -DUVW_BUILD_TESTING=ON`
* `$ make` * `$ make`
* `$ ctest -j4 -R uvw` * `$ ctest -j4 -R uvw`
@ -410,6 +418,18 @@ uv_tcp_t *handle = tcp->raw();
Go the raw way at your own risk, but do not expect any support in case of bugs. 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 # Contributors
If you want to contribute, please send patches as pull requests against the If you want to contribute, please send patches as pull requests against the
@ -420,7 +440,7 @@ who has partecipated so far.
# License # License
Code and documentation Copyright (c) 2016-2023 Michele Caini.<br/> Code and documentation Copyright (c) 2016-2024 Michele Caini.<br/>
Logo Copyright (c) 2018-2021 Richard Caseres. Logo Copyright (c) 2018-2021 Richard Caseres.
Code and documentation released under Code and documentation released under
@ -428,15 +448,9 @@ Code and documentation released under
Logo released under Logo released under
[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
<!--
@cond TURN_OFF_DOXYGEN
-->
# Support # Support
If you want to support this project, you can If you want to support this project, you can
[offer me](https://github.com/users/skypjack/sponsorship) an espresso.<br/> [offer me](https://github.com/users/skypjack/sponsorship) an espresso.<br/>
If you find that it's not enough, feel free to If you find that it's not enough, feel free to
[help me](https://www.paypal.me/skypjack) the way you prefer. [help me](https://www.paypal.me/skypjack) the way you prefer.
<!--
@endcond TURN_OFF_DOXYGEN
-->

View File

@ -13,7 +13,7 @@ class UVWConan(ConanFile):
exports = "LICENSE" exports = "LICENSE"
exports_sources = "src/*" exports_sources = "src/*"
no_copy_source = True no_copy_source = True
requires = "libuv/1.46.0@bincrafters/stable" requires = "libuv/1.49.0@bincrafters/stable"
def package(self): def package(self):
self.copy(pattern="LICENSE", dst="licenses") self.copy(pattern="LICENSE", dst="licenses")

View File

@ -1,4 +1,4 @@
# Doxyfile 1.9.6 # Doxyfile 1.10.0
# This file describes the settings to be used by the documentation system # This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project. # doxygen (www.doxygen.org) for a project.
@ -63,6 +63,12 @@ PROJECT_BRIEF =
PROJECT_LOGO = PROJECT_LOGO =
# With the PROJECT_ICON tag one can specify an icon that is included in the tabs
# when the HTML document is shown. Doxygen will copy the logo to the output
# directory.
PROJECT_ICON =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is # into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If # entered, it will be relative to the location where doxygen was started. If
@ -353,6 +359,17 @@ MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5 TOC_INCLUDE_HEADINGS = 5
# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to
# generate identifiers for the Markdown headings. Note: Every identifier is
# unique.
# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a
# sequence number starting at 0 and GITHUB use the lower case version of title
# with any whitespace replaced by '-' and punctuation characters removed.
# The default value is: DOXYGEN.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
MARKDOWN_ID_STYLE = GITHUB
# When enabled doxygen tries to link words that correspond to documented # When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can # classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or # be prevented in individual cases by putting a % sign in front of the word or
@ -477,6 +494,14 @@ LOOKUP_CACHE_SIZE = 0
NUM_PROC_THREADS = 1 NUM_PROC_THREADS = 1
# If the TIMESTAMP tag is set different from NO then each generated page will
# contain the date or date and time when the page was generated. Setting this to
# NO can help when comparing the output of multiple runs.
# Possible values are: YES, NO, DATETIME and DATE.
# The default value is: NO.
TIMESTAMP = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Build related configuration options # Build related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -862,7 +887,14 @@ WARN_IF_UNDOC_ENUM_VAL = NO
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
# at the end of the doxygen process doxygen will return with a non-zero status. # at the end of the doxygen process doxygen will return with a non-zero status.
# Possible values are: NO, YES and FAIL_ON_WARNINGS. # If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves
# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not
# write the warning messages in between other messages but write them at the end
# of a run, in case a WARN_LOGFILE is defined the warning messages will be
# besides being in the defined file also be shown at the end of a run, unless
# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case
# the behavior will remain as with the setting FAIL_ON_WARNINGS.
# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
# The default value is: NO. # The default value is: NO.
WARN_AS_ERROR = NO WARN_AS_ERROR = NO
@ -942,12 +974,12 @@ INPUT_FILE_ENCODING =
# Note the list of default checked file patterns might differ from the list of # Note the list of default checked file patterns might differ from the list of
# default file extension mappings. # default file extension mappings.
# #
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, # *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d,
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C # *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, # be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.vhdl, *.ucf, *.qsf and *.ice. # *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h \ FILE_PATTERNS = *.h \
*.hpp \ *.hpp \
@ -990,9 +1022,6 @@ EXCLUDE_PATTERNS =
# output. The symbol name can be a fully qualified name, a word, or if the # output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass, # wildcard * is used, a substring. Examples: ANamespace, AClass,
# ANamespace::AClass, ANamespace::*Test # ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS = EXCLUDE_SYMBOLS =
@ -1106,7 +1135,8 @@ FORTRAN_COMMENT_AFTER = 72
SOURCE_BROWSER = YES SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body of functions, # Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation. # multi-line macros, enums or list initialized variables directly into the
# documentation.
# The default value is: NO. # The default value is: NO.
INLINE_SOURCES = NO INLINE_SOURCES = NO
@ -1375,15 +1405,6 @@ HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80 HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that # documentation will contain a main index with vertical navigation menus that
# are dynamically created via JavaScript. If disabled, the navigation index will # are dynamically created via JavaScript. If disabled, the navigation index will
@ -1403,6 +1424,33 @@ HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO HTML_DYNAMIC_SECTIONS = NO
# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be
# dynamically folded and expanded in the generated HTML source code.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_CODE_FOLDING = YES
# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in
# the top right corner of code and text fragments that allows the user to copy
# its content to the clipboard. Note this only works if supported by the browser
# and the web page is served via a secure context (see:
# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file:
# protocol.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COPY_CLIPBOARD = YES
# Doxygen stores a couple of settings persistently in the browser (via e.g.
# cookies). By default these settings apply to all HTML pages generated by
# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store
# the settings under a project specific key, such that the user preferences will
# be stored separately.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_PROJECT_COOKIE =
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand # shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to # and collapse entries dynamically later on. Doxygen will expand the tree to
@ -1533,6 +1581,16 @@ BINARY_TOC = NO
TOC_EXPAND = NO TOC_EXPAND = NO
# The SITEMAP_URL tag is used to specify the full URL of the place where the
# generated documentation will be placed on the server by the user during the
# deployment of the documentation. The generated sitemap is called sitemap.xml
# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL
# is specified no sitemap is generated. For information about the sitemap
# protocol see https://www.sitemaps.org
# This tag requires that the tag GENERATE_HTML is set to YES.
SITEMAP_URL =
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
@ -2021,9 +2079,16 @@ PDF_HYPERLINKS = YES
USE_PDFLATEX = YES USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode # The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error.
# command to the generated LaTeX files. This will instruct LaTeX to keep running # Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch
# if errors occur, instead of asking the user for help. # mode nothing is printed on the terminal, errors are scrolled as if <return> is
# hit at every error; missing files that TeX tries to input or request from
# keyboard input (\read on a not open input stream) cause the job to abort,
# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,
# but there is no possibility of user interaction just like in batch mode,
# SCROLL In scroll mode, TeX will stop only for missing files to input or if
# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at
# each error, asking for user intervention.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@ -2044,14 +2109,6 @@ LATEX_HIDE_INDICES = NO
LATEX_BIB_STYLE = plain LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
# path from which the emoji images will be read. If a relative path is entered, # path from which the emoji images will be read. If a relative path is entered,
# it will be relative to the LATEX_OUTPUT directory. If left blank the # it will be relative to the LATEX_OUTPUT directory. If left blank the
@ -2217,13 +2274,39 @@ DOCBOOK_OUTPUT = docbook
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures # AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures
# the structure of the code including all documentation. Note that this feature # the structure of the code including all documentation. Note that this feature
# is still experimental and incomplete at the moment. # is still experimental and incomplete at the moment.
# The default value is: NO. # The default value is: NO.
GENERATE_AUTOGEN_DEF = NO GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to Sqlite3 output
#---------------------------------------------------------------------------
# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3
# database with symbols found by doxygen stored in tables.
# The default value is: NO.
GENERATE_SQLITE3 = NO
# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be
# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put
# in front of it.
# The default directory is: sqlite3.
# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
SQLITE3_OUTPUT = sqlite3
# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db
# database file will be recreated with each doxygen run. If set to NO, doxygen
# will warn if a database file is already found and not modify it.
# The default value is: YES.
# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
SQLITE3_RECREATE_DB = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the Perl module output # Configuration options related to the Perl module output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -2366,15 +2449,15 @@ TAGFILES =
GENERATE_TAGFILE = GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in # If the ALLEXTERNALS tag is set to YES, all external classes and namespaces
# the class index. If set to NO, only the inherited external classes will be # will be listed in the class and namespace index. If set to NO, only the
# listed. # inherited external classes will be listed.
# The default value is: NO. # The default value is: NO.
ALLEXTERNALS = NO ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be # in the topic index. If set to NO, only the current project's groups will be
# listed. # listed.
# The default value is: YES. # The default value is: YES.
@ -2388,16 +2471,9 @@ EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES EXTERNAL_PAGES = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the dot tool # Configuration options related to diagram generator tools
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance # If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class. # and usage relations if the target is undocumented or is not a class.
# The default value is: YES. # The default value is: YES.
@ -2406,7 +2482,7 @@ HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see: # available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is # Bell Labs. The other options in this section have no effect if this option is
# set to NO # set to NO
# The default value is: NO. # The default value is: NO.
@ -2459,13 +2535,19 @@ DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
DOT_FONTPATH = DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a # If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will
# graph for each documented class showing the direct and indirect inheritance # generate a graph for each documented class showing the direct and indirect
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, # inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set # HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case
# to TEXT the direct and indirect inheritance relations will be shown as texts / # the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the
# links. # CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.
# Possible values are: NO, YES, TEXT and GRAPH. # If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance
# relations will be shown as texts / links. Explicit enabling an inheritance
# graph or choosing a different representation for an inheritance graph of a
# specific class, can be accomplished by means of the command \inheritancegraph.
# Disabling an inheritance graph can be accomplished by means of the command
# \hideinheritancegraph.
# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.
# The default value is: YES. # The default value is: YES.
CLASS_GRAPH = YES CLASS_GRAPH = YES
@ -2473,15 +2555,21 @@ CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation # graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the # dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes. # class with other documented classes. Explicit enabling a collaboration graph,
# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the
# command \collaborationgraph. Disabling a collaboration graph can be
# accomplished by means of the command \hidecollaborationgraph.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies. See also the chapter Grouping # groups, showing the direct groups dependencies. Explicit enabling a group
# in the manual. # dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means
# of the command \groupgraph. Disabling a directory graph can be accomplished by
# means of the command \hidegroupgraph. See also the chapter Grouping in the
# manual.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2523,8 +2611,8 @@ DOT_UML_DETAILS = NO
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
# to display on a single line. If the actual line length exceeds this threshold # to display on a single line. If the actual line length exceeds this threshold
# significantly it will wrapped across multiple lines. Some heuristics are apply # significantly it will be wrapped across multiple lines. Some heuristics are
# to avoid ugly line breaks. # applied to avoid ugly line breaks.
# Minimum value: 0, maximum value: 1000, default value: 17. # Minimum value: 0, maximum value: 1000, default value: 17.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2541,7 +2629,9 @@ TEMPLATE_RELATIONS = NO
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the # YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented # direct and indirect include dependencies of the file with other documented
# files. # files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO,
# can be accomplished by means of the command \includegraph. Disabling an
# include graph can be accomplished by means of the command \hideincludegraph.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2550,7 +2640,10 @@ INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing # set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented # the direct and indirect include dependencies of the file with other documented
# files. # files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set
# to NO, can be accomplished by means of the command \includedbygraph. Disabling
# an included by graph can be accomplished by means of the command
# \hideincludedbygraph.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2590,7 +2683,10 @@ GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The # dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the # dependency relations are determined by the #include relations between the
# files in the directories. # files in the directories. Explicit enabling a directory graph, when
# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command
# \directorygraph. Disabling a directory graph can be accomplished by means of
# the command \hidedirectorygraph.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@ -2606,7 +2702,7 @@ DIR_GRAPH_MAX_DEPTH = 1
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section # generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see: # output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)). # https://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this # to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement). # requirement).
@ -2643,11 +2739,12 @@ DOT_PATH =
DOTFILE_DIRS = DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that # You can include diagrams made with dia in doxygen documentation. Doxygen will
# contain msc files that are included in the documentation (see the \mscfile # then run dia to produce the diagram and insert it in the documentation. The
# command). # DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
MSCFILE_DIRS = DIA_PATH =
# The DIAFILE_DIRS tag can be used to specify one or more directories that # The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile # contain dia files that are included in the documentation (see the \diafile
@ -2724,3 +2821,19 @@ GENERATE_LEGEND = YES
# The default value is: YES. # The default value is: YES.
DOT_CLEANUP = YES DOT_CLEANUP = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will
# use a built-in version of mscgen tool to produce the charts. Alternatively,
# the MSCGEN_TOOL tag can also specify the name an external tool. For instance,
# specifying prog as the value, doxygen will call the tool as prog -T
# <outfile_format> -o <outputfile> <inputfile>. The external tool should support
# output file formats "png", "eps", "svg", and "ismap".
MSCGEN_TOOL =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =

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

View File

@ -42,17 +42,17 @@ function(add_uvw_library LIB_NAME)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
if(USE_ASAN) if(UVW_USE_ASAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>) target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>) target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
endif() endif()
if(USE_UBSAN) if(UVW_USE_UBSAN)
target_compile_options(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer>) 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>) target_link_libraries(${LIB_NAME} PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
endif() endif()
if(HAS_LIBCPP) if(UVW_HAS_LIBCPP)
target_compile_options(${LIB_NAME} BEFORE PUBLIC -stdlib=libc++) target_compile_options(${LIB_NAME} BEFORE PUBLIC -stdlib=libc++)
endif() endif()
endfunction() endfunction()
@ -61,18 +61,18 @@ endfunction()
# Build and install libraries # Build and install libraries
# #
if (BUILD_UVW_SHARED_LIB) if (UVW_BUILD_SHARED_LIB)
add_library(uvw SHARED) add_library(uvw SHARED)
add_library(uvw::uvw-shared ALIAS uvw) 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 libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(FETCH_LIBUV OR libuv_FOUND) if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-shared) target_link_libraries(uvw PUBLIC uv::uv-shared)
endif() endif()
else() else()
add_library(uvw STATIC) add_library(uvw STATIC)
add_library(uvw::uvw-static ALIAS uvw) 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 libuv is not fetched by ourselves, it's the caller's responsibility to make sure of the linkage.
if(FETCH_LIBUV OR libuv_FOUND) if(UVW_FETCH_LIBUV OR libuv_FOUND)
target_link_libraries(uvw PUBLIC uv::uv-static) target_link_libraries(uvw PUBLIC uv::uv-static)
endif() endif()
endif() endif()

View File

@ -1,22 +1,2 @@
#ifdef UVW_AS_LIB #include "async.h"
# include "async.h" #include "async.ipp"
#endif
#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

View File

@ -32,7 +32,7 @@ public:
* *
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Wakeups the event loop and emits the async event. * @brief Wakeups the event loop and emits the async event.
@ -52,7 +52,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "async.cpp" # include "async.ipp"
#endif #endif
#endif // UVW_ASYNC_INCLUDE_H #endif // UVW_ASYNC_INCLUDE_H

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

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB #include "check.h"
# include "check.h" #include "check.ipp"
#endif
#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

View File

@ -28,7 +28,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the handle. * @brief Starts the handle.
@ -50,7 +50,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "check.cpp" # include "check.ipp"
#endif #endif
#endif // UVW_CHECK_INCLUDE_H #endif // UVW_CHECK_INCLUDE_H

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

View File

@ -1,93 +1,2 @@
#ifdef UVW_AS_LIB #include "dns.h"
# include "dns.h" #include "dns.ipp"
#endif
#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(socket_address addr, int flags) {
return name_info(std::move(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(socket_address addr, int flags) {
return name_info_sync(addr.ip, addr.port, flags);
}
} // namespace uvw

View File

@ -171,7 +171,7 @@ public:
* @param flags Optional flags that modify the behavior of `getnameinfo`. * @param flags Optional flags that modify the behavior of `getnameinfo`.
* @return Underlying return value. * @return Underlying return value.
*/ */
int name_info(socket_address addr, int flags = 0); int name_info(const socket_address &addr, int flags = 0);
/** /**
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo). * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
@ -214,13 +214,13 @@ public:
* * A `const char *` containing a valid hostname. * * A `const char *` containing a valid hostname.
* * A `const char *` containing a valid service name. * * A `const char *` containing a valid service name.
*/ */
std::pair<bool, std::pair<const char *, const char *>> name_info_sync(socket_address addr, int flags = 0); std::pair<bool, std::pair<const char *, const char *>> name_info_sync(const socket_address &addr, int flags = 0);
}; };
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "dns.cpp" # include "dns.ipp"
#endif #endif
#endif // UVW_DNS_INCLUDE_H #endif // UVW_DNS_INCLUDE_H

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

View File

@ -1,29 +1,2 @@
#ifdef UVW_AS_LIB #include "emitter.h"
# include "emitter.h" #include "emitter.ipp"
#endif
#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

View File

@ -37,7 +37,7 @@ struct error_event {
* @param sys A platform dependent error code. * @param sys A platform dependent error code.
* @return The `libuv` error code equivalent to the given platform dependent error code. * @return The `libuv` error code equivalent to the given platform dependent error code.
*/ */
static int translate(int sys) noexcept; [[nodiscard]] static int translate(int sys) noexcept;
/** /**
* @brief Returns the error message for the given error code. * @brief Returns the error message for the given error code.
@ -46,7 +46,7 @@ struct error_event {
* *
* @return The error message for the given error code. * @return The error message for the given error code.
*/ */
const char *what() const noexcept; [[nodiscard]] const char *what() const noexcept;
/** /**
* @brief Returns the error name for the given error code. * @brief Returns the error name for the given error code.
@ -55,13 +55,13 @@ struct error_event {
* *
* @return The error name for the given error code. * @return The error name for the given error code.
*/ */
const char *name() const noexcept; [[nodiscard]] const char *name() const noexcept;
/** /**
* @brief Gets the underlying error code, that is an error constant of `libuv`. * @brief Gets the underlying error code, that is an error constant of `libuv`.
* @return The underlying error code. * @return The underlying error code.
*/ */
int code() const noexcept; [[nodiscard]] int code() const noexcept;
/** /**
* @brief Checks if the event contains a valid error code. * @brief Checks if the event contains a valid error code.
@ -70,7 +70,7 @@ struct error_event {
explicit operator bool() const noexcept; explicit operator bool() const noexcept;
private: private:
const int ec; int ec;
}; };
/** /**
@ -87,12 +87,12 @@ public:
private: private:
template<typename Type> template<typename Type>
const auto &handler() const noexcept { [[nodiscard]] const auto &handler() const noexcept {
return std::get<listener_t<Type>>(handlers); return std::get<listener_t<Type>>(handlers);
} }
template<typename Type> template<typename Type>
auto &handler() noexcept { [[nodiscard]] auto &handler() noexcept {
return std::get<listener_t<Type>>(handlers); return std::get<listener_t<Type>>(handlers);
} }
@ -142,7 +142,7 @@ public:
* false otherwise. * false otherwise.
*/ */
template<typename Type> template<typename Type>
bool has() const noexcept { [[nodiscard]] bool has() const noexcept {
return static_cast<bool>(handler<Type>()); return static_cast<bool>(handler<Type>());
} }
@ -153,7 +153,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "emitter.cpp" # include "emitter.ipp"
#endif #endif
#endif // UVW_EMITTER_INCLUDE_H #endif // UVW_EMITTER_INCLUDE_H

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

View File

@ -13,21 +13,21 @@
* two values provided. * two values provided.
*/ */
template<typename Type> template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)> [[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator|(const Type lhs, const Type rhs) noexcept { 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)); return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
} }
/*! @copydoc operator| */ /*! @copydoc operator| */
template<typename Type> template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)> [[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator&(const Type lhs, const Type rhs) noexcept { 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)); return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
} }
/*! @copydoc operator| */ /*! @copydoc operator| */
template<typename Type> template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)> [[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator^(const Type lhs, const Type rhs) noexcept { 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)); return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
} }
@ -40,35 +40,35 @@ operator^(const Type lhs, const Type rhs) noexcept {
* value provided. * value provided.
*/ */
template<typename Type> template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM)> [[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM)>
operator~(const Type value) noexcept { operator~(const Type value) noexcept {
return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value)); return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
} }
/*! @copydoc operator~ */ /*! @copydoc operator~ */
template<typename Type> template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM, bool{})> [[nodiscard]] constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM, bool{})>
operator!(const Type value) noexcept { operator!(const Type value) noexcept {
return !static_cast<std::underlying_type_t<Type>>(value); return !static_cast<std::underlying_type_t<Type>>(value);
} }
/*! @copydoc operator| */ /*! @copydoc operator| */
template<typename Type> template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &> constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator|=(Type &lhs, const Type rhs) noexcept { operator|=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs | rhs)); return (lhs = (lhs | rhs));
} }
/*! @copydoc operator| */ /*! @copydoc operator| */
template<typename Type> template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &> constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator&=(Type &lhs, const Type rhs) noexcept { operator&=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs & rhs)); return (lhs = (lhs & rhs));
} }
/*! @copydoc operator| */ /*! @copydoc operator| */
template<typename Type> template<typename Type>
constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::_UVW_ENUM) &> constexpr std::enable_if_t<std::is_enum_v<Type>, decltype(Type::UVW_ENUM) &>
operator^=(Type &lhs, const Type rhs) noexcept { operator^=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs ^ rhs)); return (lhs = (lhs ^ rhs));
} }

View File

@ -1,553 +1,2 @@
#ifdef UVW_AS_LIB #include "fs.h"
# include "fs.h" #include "fs.ipp"
#endif
#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::unique_ptr<char[]>{new char[len]};
buffer = uv_buf_init(current.get(), len);
uv_buf_t bufs[] = {buffer};
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), raw(), file, bufs, 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::unique_ptr<char[]>{new char[len]};
buffer = uv_buf_init(current.get(), len);
uv_buf_t bufs[] = {buffer};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_read(parent().raw(), req, file, bufs, 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);
uv_buf_t bufs[] = {uv_buf_init(current.get(), len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs, 1, offset, &fs_request_callback);
}
UVW_INLINE void file_req::write(char *buf, unsigned int len, int64_t offset) {
uv_buf_t bufs[] = {uv_buf_init(buf, len)};
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), raw(), file, bufs, 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);
uv_buf_t bufs[] = {uv_buf_init(current.get(), len)};
auto req = raw();
uv_fs_req_cleanup(this->raw());
uv_fs_write(parent().raw(), req, file, bufs, 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[0].type);
ret.second.second = dirents[0].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[0].type), dirents[0].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

View File

@ -91,20 +91,20 @@ enum class uvw_file_open_flags : int {
TEMPORARY = UV_FS_O_TEMPORARY, TEMPORARY = UV_FS_O_TEMPORARY,
TRUNC = UV_FS_O_TRUNC, TRUNC = UV_FS_O_TRUNC,
WRONLY = UV_FS_O_WRONLY, WRONLY = UV_FS_O_WRONLY,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
enum class uvw_copy_file_flags : int { enum class uvw_copy_file_flags : int {
EXCL = UV_FS_COPYFILE_EXCL, EXCL = UV_FS_COPYFILE_EXCL,
FICLONE = UV_FS_COPYFILE_FICLONE, FICLONE = UV_FS_COPYFILE_FICLONE,
FICLONE_FORCE = UV_FS_COPYFILE_FICLONE_FORCE, FICLONE_FORCE = UV_FS_COPYFILE_FICLONE_FORCE,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
enum class uvw_symlink_flags : int { enum class uvw_symlink_flags : int {
DIR = UV_FS_SYMLINK_DIR, DIR = UV_FS_SYMLINK_DIR,
JUNCTION = UV_FS_SYMLINK_JUNCTION, JUNCTION = UV_FS_SYMLINK_JUNCTION,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
} // namespace details } // namespace details
@ -263,7 +263,7 @@ public:
using fs_request::fs_request; using fs_request::fs_request;
~file_req() noexcept; ~file_req() noexcept override;
/** /**
* @brief Async [close](http://linux.die.net/man/2/close). * @brief Async [close](http://linux.die.net/man/2/close).
@ -595,7 +595,7 @@ public:
using fs_request::fs_request; using fs_request::fs_request;
~fs_req() noexcept; ~fs_req() noexcept override;
/** /**
* @brief Async [unlink](http://linux.die.net/man/2/unlink). * @brief Async [unlink](http://linux.die.net/man/2/unlink).
@ -886,7 +886,7 @@ public:
* @param path New path, as described in the official documentation. * @param path New path, as described in the official documentation.
* @param flags Optional additional flags. * @param flags Optional additional flags.
*/ */
void copyfile(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::_UVW_ENUM); void copyfile(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::UVW_ENUM);
/** /**
* @brief Copies a file synchronously from a path to a new one. * @brief Copies a file synchronously from a path to a new one.
@ -907,7 +907,7 @@ public:
* @param flags Optional additional flags. * @param flags Optional additional flags.
* @return True in case of success, false otherwise. * @return True in case of success, false otherwise.
*/ */
bool copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::_UVW_ENUM); bool copyfile_sync(const std::string &old, const std::string &path, copy_file_flags flags = copy_file_flags::UVW_ENUM);
/** /**
* @brief Async [access](http://linux.die.net/man/2/access). * @brief Async [access](http://linux.die.net/man/2/access).
@ -1003,7 +1003,7 @@ public:
* @param path New path, as described in the official documentation. * @param path New path, as described in the official documentation.
* @param flags Optional additional flags. * @param flags Optional additional flags.
*/ */
void symlink(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::_UVW_ENUM); void symlink(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::UVW_ENUM);
/** /**
* @brief Sync [symlink](http://linux.die.net/man/2/symlink). * @brief Sync [symlink](http://linux.die.net/man/2/symlink).
@ -1020,7 +1020,7 @@ public:
* @param flags Flags, as described in the official documentation. * @param flags Flags, as described in the official documentation.
* @return True in case of success, false otherwise. * @return True in case of success, false otherwise.
*/ */
bool symlink_sync(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::_UVW_ENUM); bool symlink_sync(const std::string &old, const std::string &path, symlink_flags flags = symlink_flags::UVW_ENUM);
/** /**
* @brief Async [readlink](http://linux.die.net/man/2/readlink). * @brief Async [readlink](http://linux.die.net/man/2/readlink).
@ -1196,7 +1196,7 @@ public:
std::pair<bool, std::pair<entry_type, const char *>> readdir_sync(); std::pair<bool, std::pair<entry_type, const char *>> readdir_sync();
private: private:
uv_dirent_t dirents[1]; uv_dirent_t dirents;
}; };
/*! @brief Helper functions. */ /*! @brief Helper functions. */
@ -1229,7 +1229,7 @@ struct fs_helper {
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "fs.cpp" # include "fs.ipp"
#endif #endif
#endif // UVW_FS_INCLUDE_H #endif // UVW_FS_INCLUDE_H

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

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB #include "fs_event.h"
# include "fs_event.h" #include "fs_event.ipp"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE fs_event_event::fs_event_event(const char *pathname, details::uvw_fs_event events)
: filename{pathname}, flags{std::move(events)} {}
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

View File

@ -18,7 +18,7 @@ enum class uvw_fs_event_flags : std::underlying_type_t<uv_fs_event_flags> {
WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY, WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY,
STAT = UV_FS_EVENT_STAT, STAT = UV_FS_EVENT_STAT,
RECURSIVE = UV_FS_EVENT_RECURSIVE, RECURSIVE = UV_FS_EVENT_RECURSIVE,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
enum class uvw_fs_event : std::underlying_type_t<uv_fs_event> { enum class uvw_fs_event : std::underlying_type_t<uv_fs_event> {
@ -77,7 +77,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts watching the specified path. * @brief Starts watching the specified path.
@ -96,7 +96,7 @@ public:
* @param flags Additional flags to control the behavior. * @param flags Additional flags to control the behavior.
* @return Underlying return value. * @return Underlying return value.
*/ */
int start(const std::string &path, event_flags flags = event_flags::_UVW_ENUM); int start(const std::string &path, event_flags flags = event_flags::UVW_ENUM);
/** /**
* @brief Stops polling the file descriptor. * @brief Stops polling the file descriptor.
@ -114,7 +114,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "fs_event.cpp" # include "fs_event.ipp"
#endif #endif
#endif // UVW_FS_EVENT_INCLUDE_H #endif // UVW_FS_EVENT_INCLUDE_H

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

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB #include "fs_poll.h"
# include "fs_poll.h" #include "fs_poll.ipp"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE fs_poll_event::fs_poll_event(file_info previous, file_info current) noexcept
: prev{std::move(previous)}, curr{std::move(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

@ -40,7 +40,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the handle. * @brief Starts the handle.
@ -70,7 +70,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "fs_poll.cpp" # include "fs_poll.ipp"
#endif #endif
#endif // UVW_FS_POLL_INCLUDE_H #endif // UVW_FS_POLL_INCLUDE_H

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

@ -29,11 +29,11 @@ protected:
ref.publish(close_event{}); ref.publish(close_event{});
} }
uv_handle_t *as_uv_handle() { [[nodiscard]] uv_handle_t *as_uv_handle() {
return reinterpret_cast<uv_handle_t *>(this->raw()); return reinterpret_cast<uv_handle_t *>(this->raw());
} }
const uv_handle_t *as_uv_handle() const { [[nodiscard]] const uv_handle_t *as_uv_handle() const {
return reinterpret_cast<const uv_handle_t *>(this->raw()); return reinterpret_cast<const uv_handle_t *>(this->raw());
} }
@ -49,7 +49,7 @@ public:
* *
* @return The actual category of the handle. * @return The actual category of the handle.
*/ */
handle_category category() const noexcept { [[nodiscard]] handle_category category() const noexcept {
return handle_category{as_uv_handle()->type}; return handle_category{as_uv_handle()->type};
} }
@ -62,7 +62,7 @@ public:
* *
* @return The actual type of the handle. * @return The actual type of the handle.
*/ */
handle_type type() const noexcept { [[nodiscard]] handle_type type() const noexcept {
return utilities::guess_handle(category()); return utilities::guess_handle(category());
} }
@ -85,7 +85,7 @@ public:
* *
* @return True if the handle is active, false otherwise. * @return True if the handle is active, false otherwise.
*/ */
bool active() const noexcept { [[nodiscard]] bool active() const noexcept {
return !!uv_is_active(as_uv_handle()); return !!uv_is_active(as_uv_handle());
} }
@ -97,7 +97,7 @@ public:
* *
* @return True if the handle is closing or closed, false otherwise. * @return True if the handle is closing or closed, false otherwise.
*/ */
bool closing() const noexcept { [[nodiscard]] bool closing() const noexcept {
return !!uv_is_closing(as_uv_handle()); return !!uv_is_closing(as_uv_handle());
} }
@ -139,7 +139,7 @@ public:
* @brief Checks if the given handle referenced. * @brief Checks if the given handle referenced.
* @return True if the handle referenced, false otherwise. * @return True if the handle referenced, false otherwise.
*/ */
bool referenced() const noexcept { [[nodiscard]] bool referenced() const noexcept {
return !!uv_has_ref(as_uv_handle()); return !!uv_has_ref(as_uv_handle());
} }
@ -147,7 +147,7 @@ public:
* @brief Returns the size of the underlying handle type. * @brief Returns the size of the underlying handle type.
* @return The size of the underlying handle type. * @return The size of the underlying handle type.
*/ */
std::size_t size() const noexcept { [[nodiscard]] std::size_t size() const noexcept {
return uv_handle_size(as_uv_handle()->type); return uv_handle_size(as_uv_handle()->type);
} }
@ -163,7 +163,7 @@ public:
* @return The size of the send buffer, the underlying return value in case * @return The size of the send buffer, the underlying return value in case
* of errors. * of errors.
*/ */
int send_buffer_size() { [[nodiscard]] int send_buffer_size() {
int value = 0; int value = 0;
auto err = uv_send_buffer_size(as_uv_handle(), &value); auto err = uv_send_buffer_size(as_uv_handle(), &value);
return err ? err : value; return err ? err : value;
@ -180,7 +180,7 @@ public:
* *
* @return Underlying return value. * @return Underlying return value.
*/ */
int send_buffer_size(int value) { [[nodiscard]] int send_buffer_size(int value) {
return uv_send_buffer_size(as_uv_handle(), &value); return uv_send_buffer_size(as_uv_handle(), &value);
} }
@ -196,7 +196,7 @@ public:
* @return The size of the receive buffer, the underlying return value in * @return The size of the receive buffer, the underlying return value in
* case of errors. * case of errors.
*/ */
int recv_buffer_size() { [[nodiscard]] int recv_buffer_size() {
int value = 0; int value = 0;
auto err = uv_recv_buffer_size(as_uv_handle(), &value); auto err = uv_recv_buffer_size(as_uv_handle(), &value);
return err ? err : value; return err ? err : value;
@ -213,7 +213,7 @@ public:
* *
* @return Underlying return value. * @return Underlying return value.
*/ */
int recv_buffer_size(int value) { [[nodiscard]] int recv_buffer_size(int value) {
return uv_recv_buffer_size(as_uv_handle(), &value); return uv_recv_buffer_size(as_uv_handle(), &value);
} }
@ -238,7 +238,7 @@ public:
* @return The file descriptor attached to the hande or a negative value in * @return The file descriptor attached to the hande or a negative value in
* case of errors. * case of errors.
*/ */
os_file_descriptor fd() const { [[nodiscard]] os_file_descriptor fd() const {
uv_os_fd_t fd; uv_os_fd_t fd;
uv_fileno(as_uv_handle(), &fd); uv_fileno(as_uv_handle(), &fd);
return fd; return fd;

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB #include "idle.h"
# include "idle.h" #include "idle.ipp"
#endif
#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

View File

@ -36,7 +36,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the handle. * @brief Starts the handle.
@ -59,7 +59,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "idle.cpp" # include "idle.ipp"
#endif #endif
#endif // UVW_IDLE_INCLUDE_H #endif // UVW_IDLE_INCLUDE_H

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

View File

@ -1,27 +1,2 @@
#ifdef UVW_AS_LIB #include "lib.h"
# include "lib.h" #include "lib.ipp"
#endif
#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

View File

@ -43,7 +43,9 @@ public:
static_assert(std::is_function_v<F>); static_assert(std::is_function_v<F>);
F *func; F *func;
auto err = uv_dlsym(raw(), name.data(), reinterpret_cast<void **>(&func)); auto err = uv_dlsym(raw(), name.data(), reinterpret_cast<void **>(&func));
if(err) { func = nullptr; } if(err) {
func = nullptr;
}
return func; return func;
} }
@ -51,7 +53,7 @@ public:
* @brief Returns the last error message, if any. * @brief Returns the last error message, if any.
* @return The last error message, if any. * @return The last error message, if any.
*/ */
const char *error() const noexcept; [[nodiscard]] const char *error() const noexcept;
private: private:
bool opened; bool opened;
@ -60,7 +62,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "lib.cpp" # include "lib.ipp"
#endif #endif
#endif // UVW_LIB_INCLUDE_H #endif // UVW_LIB_INCLUDE_H

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

View File

@ -1,120 +1,2 @@
#ifdef UVW_AS_LIB #include "loop.h"
# include "loop.h" #include "loop.ipp"
#endif
#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

View File

@ -68,6 +68,16 @@ class loop final: public emitter<loop>, public std::enable_shared_from_this<loop
explicit uv_token(int) {} 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; loop(std::unique_ptr<uv_loop_t, deleter> ptr) noexcept;
public: public:
@ -114,7 +124,7 @@ public:
loop &operator=(const loop &) = delete; loop &operator=(const loop &) = delete;
loop &operator=(loop &&other) = delete; loop &operator=(loop &&other) = delete;
~loop() noexcept; ~loop() noexcept override;
/** /**
* @brief Sets additional loop options. * @brief Sets additional loop options.
@ -153,8 +163,7 @@ public:
template<typename R, typename... Args> template<typename R, typename... Args>
std::shared_ptr<R> resource(Args &&...args) { std::shared_ptr<R> resource(Args &&...args) {
auto ptr = uninitialized_resource<R>(std::forward<Args>(args)...); auto ptr = uninitialized_resource<R>(std::forward<Args>(args)...);
ptr = (ptr->init() == 0) ? ptr : nullptr; return (init(0, *ptr) == 0) ? ptr : nullptr;
return ptr;
} }
/** /**
@ -278,9 +287,9 @@ public:
*/ */
template<typename Func> template<typename Func>
void walk(Func callback) { void walk(Func callback) {
auto func = [](uv_handle_t *hndl, void *func) { auto func = [](uv_handle_t *hndl, void *callback_func) {
if(hndl->data) { if(hndl->data) {
auto &cb = *static_cast<Func *>(func); auto &cb = *static_cast<Func *>(callback_func);
switch(utilities::guess_handle(handle_category{hndl->type})) { switch(utilities::guess_handle(handle_category{hndl->type})) {
case handle_type::ASYNC: case handle_type::ASYNC:
@ -424,7 +433,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "loop.cpp" # include "loop.ipp"
#endif #endif
#endif // UVW_LOOP_INCLUDE_H #endif // UVW_LOOP_INCLUDE_H

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

View File

@ -1,62 +1,2 @@
#ifdef UVW_AS_LIB #include "pipe.h"
# include "pipe.h" #include "pipe.ipp"
#endif
#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);
return connect->connect(&uv_pipe_connect2, raw(), name.data(), name.size(), no_truncate * UV_PIPE_NO_TRUNCATE);
}
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

View File

@ -19,7 +19,7 @@ namespace details {
enum class uvw_chmod_flags : std::underlying_type_t<uv_poll_event> { enum class uvw_chmod_flags : std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE, READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE, WRITABLE = UV_WRITABLE,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
} }
@ -45,7 +45,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Opens an existing file descriptor or HANDLE as a pipe. * @brief Opens an existing file descriptor or HANDLE as a pipe.
@ -158,7 +158,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "pipe.cpp" # include "pipe.ipp"
#endif #endif
#endif // UVW_PIPE_INCLUDE_H #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

View File

@ -1,43 +1,2 @@
#ifdef UVW_AS_LIB #include "poll.h"
# include "poll.h" #include "poll.ipp"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE poll_event::poll_event(details::uvw_poll_event events) noexcept
: flags{std::move(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} {}
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

View File

@ -18,7 +18,7 @@ enum class uvw_poll_event : std::underlying_type_t<uv_poll_event> {
WRITABLE = UV_WRITABLE, WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT, DISCONNECT = UV_DISCONNECT,
PRIORITIZED = UV_PRIORITIZED, PRIORITIZED = UV_PRIORITIZED,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
} }
@ -69,7 +69,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts polling the file descriptor. * @brief Starts polling the file descriptor.
@ -113,7 +113,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "poll.cpp" # include "poll.ipp"
#endif #endif
#endif // UVW_POLL_INCLUDE_H #endif // UVW_POLL_INCLUDE_H

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

View File

@ -1,26 +1,2 @@
#ifdef UVW_AS_LIB #include "prepare.h"
# include "prepare.h" #include "prepare.ipp"
#endif
#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

View File

@ -28,7 +28,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the handle. * @brief Starts the handle.
@ -52,7 +52,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "prepare.cpp" # include "prepare.ipp"
#endif #endif
#endif // UVW_PREPARE_INCLUDE_H #endif // UVW_PREPARE_INCLUDE_H

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

View File

@ -1,111 +1,2 @@
#ifdef UVW_AS_LIB #include "process.h"
# include "process.h" #include "process.ipp"
#endif
#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
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(std::move(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

@ -25,7 +25,8 @@ enum class uvw_process_flags : std::underlying_type_t<uv_process_flags> {
WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE, WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE,
WINDOWS_HIDE_CONSOLE = UV_PROCESS_WINDOWS_HIDE_CONSOLE, WINDOWS_HIDE_CONSOLE = UV_PROCESS_WINDOWS_HIDE_CONSOLE,
WINDOWS_HIDE_GUI = UV_PROCESS_WINDOWS_HIDE_GUI, WINDOWS_HIDE_GUI = UV_PROCESS_WINDOWS_HIDE_GUI,
_UVW_ENUM = 0 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> { enum class uvw_stdio_flags : std::underlying_type_t<uv_stdio_flags> {
@ -36,7 +37,7 @@ enum class uvw_stdio_flags : std::underlying_type_t<uv_stdio_flags> {
READABLE_PIPE = UV_READABLE_PIPE, READABLE_PIPE = UV_READABLE_PIPE,
WRITABLE_PIPE = UV_WRITABLE_PIPE, WRITABLE_PIPE = UV_WRITABLE_PIPE,
OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE, OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
} // namespace details } // namespace details
@ -92,7 +93,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief spawn Starts the process. * @brief spawn Starts the process.
@ -143,6 +144,7 @@ public:
* * `process_handle::process_flags::WINDOWS_HIDE` * * `process_handle::process_flags::WINDOWS_HIDE`
* * `process_handle::process_flags::WINDOWS_HIDE_CONSOLE` * * `process_handle::process_flags::WINDOWS_HIDE_CONSOLE`
* * `process_handle::process_flags::WINDOWS_HIDE_GUI` * * `process_handle::process_flags::WINDOWS_HIDE_GUI`
* * `process_handle::process_flags::WINDOWS_FILE_PATH_EXACT_NAME`
* *
* See the official * See the official
* [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_process_flags) * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_process_flags)
@ -179,7 +181,7 @@ public:
uv_stdio_container_t container; uv_stdio_container_t container;
container.flags = static_cast<uv_stdio_flags>(flags); container.flags = static_cast<uv_stdio_flags>(flags);
container.data.stream = reinterpret_cast<uv_stream_t *>(stream.raw()); container.data.stream = reinterpret_cast<uv_stream_t *>(stream.raw());
po_stream_stdio.push_back(std::move(container)); po_stream_stdio.push_back(container);
return *this; return *this;
} }
@ -237,7 +239,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "process.cpp" # include "process.ipp"
#endif #endif
#endif // UVW_PROCESS_INCLUDE_H #endif // UVW_PROCESS_INCLUDE_H

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

@ -18,7 +18,7 @@ namespace uvw {
template<typename T, typename U, typename... E> template<typename T, typename U, typename... E>
class request: public resource<T, U, E...> { class request: public resource<T, U, E...> {
protected: protected:
static auto reserve(U *req) { [[nodiscard]] static auto reserve(U *req) {
auto ptr = static_cast<T *>(req->data)->shared_from_this(); auto ptr = static_cast<T *>(req->data)->shared_from_this();
ptr->self_reset(); ptr->self_reset();
return ptr; return ptr;
@ -47,7 +47,7 @@ public:
* @brief Returns the size of the underlying request type. * @brief Returns the size of the underlying request type.
* @return The size of the underlying request type. * @return The size of the underlying request type.
*/ */
std::size_t size() const noexcept { [[nodiscard]] std::size_t size() const noexcept {
return uv_req_size(reinterpret_cast<const uv_req_t *>(this->raw())->type); return uv_req_size(reinterpret_cast<const uv_req_t *>(this->raw())->type);
} }
}; };

View File

@ -17,7 +17,7 @@ namespace uvw {
template<typename T, typename U, typename... E> template<typename T, typename U, typename... E>
class resource: public uv_type<U>, public emitter<T, E...>, public std::enable_shared_from_this<T> { class resource: public uv_type<U>, public emitter<T, E...>, public std::enable_shared_from_this<T> {
protected: protected:
int leak_if(int err) noexcept { [[nodiscard]] int leak_if(int err) noexcept {
if(err == 0) { if(err == 0) {
self_ptr = this->shared_from_this(); self_ptr = this->shared_from_this();
} }
@ -29,7 +29,7 @@ protected:
self_ptr.reset(); self_ptr.reset();
} }
bool has_self() const noexcept { [[nodiscard]] bool has_self() const noexcept {
return static_cast<bool>(self_ptr); return static_cast<bool>(self_ptr);
} }
@ -44,7 +44,7 @@ public:
* @return User-defined data if any, an invalid pointer otherwise. * @return User-defined data if any, an invalid pointer otherwise.
*/ */
template<typename R = void> template<typename R = void>
std::shared_ptr<R> data() const { [[nodiscard]] std::shared_ptr<R> data() const {
return std::static_pointer_cast<R>(user_data); return std::static_pointer_cast<R>(user_data);
} }

View File

@ -1,37 +1,2 @@
#ifdef UVW_AS_LIB #include "signal.h"
# include "signal.h" #include "signal.ipp"
#endif
#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

View File

@ -38,7 +38,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the handle. * @brief Starts the handle.
@ -77,7 +77,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "signal.cpp" # include "signal.ipp"
#endif #endif
#endif // UVW_SIGNAL_INCLUDE_H #endif // UVW_SIGNAL_INCLUDE_H

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

View File

@ -1,33 +1,2 @@
#ifdef UVW_AS_LIB #include "stream.h"
# include "stream.h" #include "stream.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE data_event::data_event(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)},
length{len} {}
UVW_INLINE void details::connect_req::connect_callback(uv_connect_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(connect_event{});
}
}
UVW_INLINE void details::shutdown_req::shoutdown_callback(uv_shutdown_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(shutdown_event{});
}
}
UVW_INLINE int details::shutdown_req::shutdown(uv_stream_t *hndl) {
return this->leak_if(uv_shutdown(raw(), hndl, &shoutdown_callback));
}
} // namespace uvw

View File

@ -2,6 +2,7 @@
#define UVW_STREAM_INCLUDE_H #define UVW_STREAM_INCLUDE_H
#include <algorithm> #include <algorithm>
#include <array>
#include <cstddef> #include <cstddef>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
@ -142,11 +143,11 @@ class stream_handle: public handle<T, U, listen_event, end_event, connect_event,
} }
} }
uv_stream_t *as_uv_stream() { [[nodiscard]] uv_stream_t *as_uv_stream() {
return reinterpret_cast<uv_stream_t *>(this->raw()); return reinterpret_cast<uv_stream_t *>(this->raw());
} }
const uv_stream_t *as_uv_stream() const { [[nodiscard]] const uv_stream_t *as_uv_stream() const {
return reinterpret_cast<const uv_stream_t *>(this->raw()); return reinterpret_cast<const uv_stream_t *>(this->raw());
} }
@ -377,8 +378,8 @@ public:
* @return Underlying return value. * @return Underlying return value.
*/ */
int try_write(std::unique_ptr<char[]> data, unsigned int len) { int try_write(std::unique_ptr<char[]> data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)}; std::array bufs{uv_buf_init(data.get(), len)};
return uv_try_write(as_uv_stream(), bufs, 1); return uv_try_write(as_uv_stream(), bufs.data(), 1);
} }
/** /**
@ -393,8 +394,8 @@ public:
*/ */
template<typename V, typename W> template<typename V, typename W>
int try_write(std::unique_ptr<char[]> data, unsigned int len, stream_handle<V, W> &send) { int try_write(std::unique_ptr<char[]> data, unsigned int len, stream_handle<V, W> &send) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)}; std::array bufs{uv_buf_init(data.get(), len)};
return uv_try_write2(as_uv_stream(), bufs, 1, send.raw()); return uv_try_write2(as_uv_stream(), bufs.data(), 1, send.raw());
} }
/** /**
@ -408,8 +409,8 @@ public:
* @return Underlying return value. * @return Underlying return value.
*/ */
int try_write(char *data, unsigned int len) { int try_write(char *data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data, len)}; std::array bufs{uv_buf_init(data, len)};
return uv_try_write(as_uv_stream(), bufs, 1); return uv_try_write(as_uv_stream(), bufs.data(), 1);
} }
/** /**
@ -424,15 +425,15 @@ public:
*/ */
template<typename V, typename W> template<typename V, typename W>
int try_write(char *data, unsigned int len, stream_handle<V, W> &send) { int try_write(char *data, unsigned int len, stream_handle<V, W> &send) {
uv_buf_t bufs[] = {uv_buf_init(data, len)}; std::array bufs{uv_buf_init(data, len)};
return uv_try_write2(as_uv_stream(), bufs, 1, send.raw()); return uv_try_write2(as_uv_stream(), bufs.data(), 1, send.raw());
} }
/** /**
* @brief Checks if the stream is readable. * @brief Checks if the stream is readable.
* @return True if the stream is readable, false otherwise. * @return True if the stream is readable, false otherwise.
*/ */
bool readable() const noexcept { [[nodiscard]] bool readable() const noexcept {
return (uv_is_readable(as_uv_stream()) == 1); return (uv_is_readable(as_uv_stream()) == 1);
} }
@ -440,7 +441,7 @@ public:
* @brief Checks if the stream is writable. * @brief Checks if the stream is writable.
* @return True if the stream is writable, false otherwise. * @return True if the stream is writable, false otherwise.
*/ */
bool writable() const noexcept { [[nodiscard]] bool writable() const noexcept {
return (uv_is_writable(as_uv_stream()) == 1); return (uv_is_writable(as_uv_stream()) == 1);
} }
@ -467,7 +468,7 @@ public:
* @brief Gets the amount of queued bytes waiting to be sent. * @brief Gets the amount of queued bytes waiting to be sent.
* @return Amount of queued bytes waiting to be sent. * @return Amount of queued bytes waiting to be sent.
*/ */
size_t write_queue_size() const noexcept { [[nodiscard]] size_t write_queue_size() const noexcept {
return uv_stream_get_write_queue_size(as_uv_stream()); return uv_stream_get_write_queue_size(as_uv_stream());
} }
}; };
@ -475,7 +476,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "stream.cpp" # include "stream.ipp"
#endif #endif
#endif // UVW_STREAM_INCLUDE_H #endif // UVW_STREAM_INCLUDE_H

29
src/uvw/stream.ipp Normal file
View File

@ -0,0 +1,29 @@
#include "config.h"
namespace uvw {
UVW_INLINE data_event::data_event(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)},
length{len} {}
UVW_INLINE void details::connect_req::connect_callback(uv_connect_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(connect_event{});
}
}
UVW_INLINE void details::shutdown_req::shoutdown_callback(uv_shutdown_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(shutdown_event{});
}
}
UVW_INLINE int details::shutdown_req::shutdown(uv_stream_t *hndl) {
return this->leak_if(uv_shutdown(raw(), hndl, &shoutdown_callback));
}
} // namespace uvw

View File

@ -1,86 +1,2 @@
#ifdef UVW_AS_LIB #include "tcp.h"
# include "tcp.h" #include "tcp.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE tcp_handle::tcp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: stream_handle{token, std::move(ref)}, tag{f ? FLAGS : DEFAULT}, flags{f} {}
UVW_INLINE int tcp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_tcp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_tcp_init(parent().raw(), raw()));
}
}
UVW_INLINE int tcp_handle::open(os_socket_handle socket) {
return uv_tcp_open(raw(), socket);
}
UVW_INLINE bool tcp_handle::no_delay(bool value) {
return (0 == uv_tcp_nodelay(raw(), value));
}
UVW_INLINE bool tcp_handle::keep_alive(bool enable, tcp_handle::time val) {
return (0 == uv_tcp_keepalive(raw(), enable, val.count()));
}
UVW_INLINE bool tcp_handle::simultaneous_accepts(bool enable) {
return (0 == uv_tcp_simultaneous_accepts(raw(), enable));
}
UVW_INLINE int tcp_handle::bind(const sockaddr &addr, tcp_flags opts) {
return uv_tcp_bind(raw(), &addr, static_cast<uv_tcp_flags>(opts));
}
UVW_INLINE int tcp_handle::bind(const std::string &ip, unsigned int port, tcp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int tcp_handle::bind(socket_address addr, tcp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address tcp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE socket_address tcp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int tcp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int tcp_handle::connect(socket_address addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int tcp_handle::connect(const sockaddr &addr) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto req = parent().resource<details::connect_req>();
req->on<error_event>(listener);
req->on<connect_event>(listener);
return req->connect(&uv_tcp_connect, raw(), &addr);
}
UVW_INLINE int tcp_handle::close_reset() {
return uv_tcp_close_reset(raw(), &this->close_callback);
}
} // namespace uvw

View File

@ -19,7 +19,7 @@ namespace details {
enum class uvw_tcp_flags : std::underlying_type_t<uv_tcp_flags> { enum class uvw_tcp_flags : std::underlying_type_t<uv_tcp_flags> {
IPV6ONLY = UV_TCP_IPV6ONLY, IPV6ONLY = UV_TCP_IPV6ONLY,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
} }
@ -53,7 +53,7 @@ public:
* @brief Initializes the handle. No socket is created as of yet. * @brief Initializes the handle. No socket is created as of yet.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Opens an existing file descriptor or SOCKET as a TCP handle. * @brief Opens an existing file descriptor or SOCKET as a TCP handle.
@ -115,7 +115,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(const sockaddr &addr, tcp_flags opts = tcp_flags::_UVW_ENUM); int bind(const sockaddr &addr, tcp_flags opts = tcp_flags::UVW_ENUM);
/** /**
* @brief Binds the handle to an address and port. * @brief Binds the handle to an address and port.
@ -133,7 +133,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(const std::string &ip, unsigned int port, tcp_flags opts = tcp_flags::_UVW_ENUM); int bind(const std::string &ip, unsigned int port, tcp_flags opts = tcp_flags::UVW_ENUM);
/** /**
* @brief Binds the handle to an address and port. * @brief Binds the handle to an address and port.
@ -150,7 +150,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(socket_address addr, tcp_flags opts = tcp_flags::_UVW_ENUM); int bind(const socket_address &addr, tcp_flags opts = tcp_flags::UVW_ENUM);
/** /**
* @brief Gets the current address to which the handle is bound. * @brief Gets the current address to which the handle is bound.
@ -199,7 +199,7 @@ public:
* @param addr A valid instance of socket_address. * @param addr A valid instance of socket_address.
* @return Underlying return value. * @return Underlying return value.
*/ */
int connect(socket_address addr); int connect(const socket_address &addr);
/** /**
* @brief Resets a TCP connection by sending a RST packet. * @brief Resets a TCP connection by sending a RST packet.
@ -227,7 +227,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "tcp.cpp" # include "tcp.ipp"
#endif #endif
#endif // UVW_TCP_INCLUDE_H #endif // UVW_TCP_INCLUDE_H

82
src/uvw/tcp.ipp Normal file
View File

@ -0,0 +1,82 @@
#include "config.h"
namespace uvw {
UVW_INLINE tcp_handle::tcp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: stream_handle{token, std::move(ref)}, tag{f ? FLAGS : DEFAULT}, flags{f} {}
UVW_INLINE int tcp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_tcp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_tcp_init(parent().raw(), raw()));
}
}
UVW_INLINE int tcp_handle::open(os_socket_handle socket) {
return uv_tcp_open(raw(), socket);
}
UVW_INLINE bool tcp_handle::no_delay(bool value) {
return (0 == uv_tcp_nodelay(raw(), value));
}
UVW_INLINE bool tcp_handle::keep_alive(bool enable, tcp_handle::time val) {
return (0 == uv_tcp_keepalive(raw(), enable, val.count()));
}
UVW_INLINE bool tcp_handle::simultaneous_accepts(bool enable) {
return (0 == uv_tcp_simultaneous_accepts(raw(), enable));
}
UVW_INLINE int tcp_handle::bind(const sockaddr &addr, tcp_flags opts) {
return uv_tcp_bind(raw(), &addr, static_cast<uv_tcp_flags>(opts));
}
UVW_INLINE int tcp_handle::bind(const std::string &ip, unsigned int port, tcp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int tcp_handle::bind(const socket_address &addr, tcp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address tcp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE socket_address tcp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_tcp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int tcp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int tcp_handle::connect(const socket_address &addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int tcp_handle::connect(const sockaddr &addr) {
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
auto req = parent().resource<details::connect_req>();
req->on<error_event>(listener);
req->on<connect_event>(listener);
return req->connect(&uv_tcp_connect, raw(), &addr);
}
UVW_INLINE int tcp_handle::close_reset() {
return uv_tcp_close_reset(raw(), &this->close_callback);
}
} // namespace uvw

View File

@ -1,179 +1,2 @@
#ifdef UVW_AS_LIB #include "thread.h"
# include "thread.h" #include "thread.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE thread::thread(loop::token token, std::shared_ptr<loop> ref, task t, std::shared_ptr<void> d) noexcept
: uv_type{token, std::move(ref)},
data{std::move(d)},
func{std::move(t)} {}
UVW_INLINE void thread::create_callback(void *arg) {
thread &curr = *(static_cast<thread *>(arg));
curr.func(curr.data);
}
UVW_INLINE thread::type thread::self() noexcept {
return uv_thread_self();
}
UVW_INLINE int thread::getcpu() noexcept {
return uv_thread_getcpu();
}
UVW_INLINE bool thread::equal(const thread &tl, const thread &tr) noexcept {
return !(0 == uv_thread_equal(tl.raw(), tr.raw()));
}
UVW_INLINE thread::~thread() noexcept {
join();
}
UVW_INLINE bool thread::run() noexcept {
return (0 == uv_thread_create(raw(), &create_callback, this));
}
UVW_INLINE bool thread::run(create_flags opts, std::size_t stack) noexcept {
uv_thread_options_t params{static_cast<unsigned int>(opts), stack};
return (0 == uv_thread_create_ex(raw(), &params, &create_callback, this));
}
UVW_INLINE bool thread::join() noexcept {
return (0 == uv_thread_join(raw()));
}
UVW_INLINE thread_local_storage::thread_local_storage(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_key_create(uv_type::raw());
}
UVW_INLINE thread_local_storage::~thread_local_storage() noexcept {
uv_key_delete(uv_type::raw());
}
UVW_INLINE uv_once_t *once::guard() noexcept {
static uv_once_t once = UV_ONCE_INIT;
return &once;
}
UVW_INLINE mutex::mutex(loop::token token, std::shared_ptr<loop> ref, bool recursive) noexcept
: uv_type{token, std::move(ref)} {
if(recursive) {
uv_mutex_init_recursive(raw());
} else {
uv_mutex_init(raw());
}
}
UVW_INLINE mutex::~mutex() noexcept {
uv_mutex_destroy(raw());
}
UVW_INLINE void mutex::lock() noexcept {
uv_mutex_lock(raw());
}
UVW_INLINE bool mutex::try_lock() noexcept {
return (0 == uv_mutex_trylock(raw()));
}
UVW_INLINE void mutex::unlock() noexcept {
uv_mutex_unlock(raw());
}
UVW_INLINE rwlock::rwlock(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_rwlock_init(raw());
}
UVW_INLINE rwlock::~rwlock() noexcept {
uv_rwlock_destroy(raw());
}
UVW_INLINE void rwlock::rdlock() noexcept {
uv_rwlock_rdlock(raw());
}
UVW_INLINE bool rwlock::try_rdlock() noexcept {
return (0 == uv_rwlock_tryrdlock(raw()));
}
UVW_INLINE void rwlock::rdunlock() noexcept {
uv_rwlock_rdunlock(raw());
}
UVW_INLINE void rwlock::wrlock() noexcept {
uv_rwlock_wrlock(raw());
}
UVW_INLINE bool rwlock::try_wrlock() noexcept {
return (0 == uv_rwlock_trywrlock(raw()));
}
UVW_INLINE void rwlock::wrunlock() noexcept {
uv_rwlock_wrunlock(raw());
}
UVW_INLINE semaphore::semaphore(loop::token token, std::shared_ptr<loop> ref, unsigned int value) noexcept
: uv_type{token, std::move(ref)} {
uv_sem_init(raw(), value);
}
UVW_INLINE semaphore::~semaphore() noexcept {
uv_sem_destroy(raw());
}
UVW_INLINE void semaphore::post() noexcept {
uv_sem_post(raw());
}
UVW_INLINE void semaphore::wait() noexcept {
uv_sem_wait(raw());
}
UVW_INLINE bool semaphore::try_wait() noexcept {
return (0 == uv_sem_trywait(raw()));
}
UVW_INLINE condition::condition(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_cond_init(raw());
}
UVW_INLINE condition::~condition() noexcept {
uv_cond_destroy(raw());
}
UVW_INLINE void condition::signal() noexcept {
uv_cond_signal(raw());
}
UVW_INLINE void condition::broadcast() noexcept {
uv_cond_broadcast(raw());
}
UVW_INLINE void condition::wait(mutex &mtx) noexcept {
uv_cond_wait(raw(), mtx.raw());
}
UVW_INLINE bool condition::timed_wait(mutex &mtx, uint64_t timeout) noexcept {
return (0 == uv_cond_timedwait(raw(), mtx.raw(), timeout));
}
UVW_INLINE barrier::barrier(loop::token token, std::shared_ptr<loop> ref, unsigned int count) noexcept
: uv_type{token, std::move(ref)} {
uv_barrier_init(raw(), count);
}
UVW_INLINE barrier::~barrier() noexcept {
uv_barrier_destroy(raw());
}
UVW_INLINE bool barrier::wait() noexcept {
return (0 == uv_barrier_wait(raw()));
}
} // namespace uvw

View File

@ -22,7 +22,15 @@ enum class uvw_thread_create_flags : std::underlying_type_t<uv_thread_create_fla
THREAD_HAS_STACK_SIZE = UV_THREAD_HAS_STACK_SIZE THREAD_HAS_STACK_SIZE = UV_THREAD_HAS_STACK_SIZE
}; };
} enum class uvw_thread_priority : int {
THREAD_PRIO_HIGHEST = UV_THREAD_PRIORITY_HIGHEST,
THREAD_PRIO_ABOVE_NORMAL = UV_THREAD_PRIORITY_ABOVE_NORMAL,
THREAD_PRIO_NORMAL = UV_THREAD_PRIORITY_NORMAL,
THREAD_PRIO_BELOW_NORMAL = UV_THREAD_PRIORITY_BELOW_NORMAL,
THREAD_PRIO_LOWEST = UV_THREAD_PRIORITY_LOWEST
};
} // namespace details
class thread; class thread;
class thread_local_storage; class thread_local_storage;
@ -49,6 +57,7 @@ class thread final: public uv_type<uv_thread_t> {
public: public:
using create_flags = details::uvw_thread_create_flags; using create_flags = details::uvw_thread_create_flags;
using thread_priority = details::uvw_thread_priority;
using task = internal_task; using task = internal_task;
using type = uv_thread_t; using type = uv_thread_t;
@ -74,6 +83,23 @@ public:
*/ */
static bool equal(const thread &tl, const thread &tr) noexcept; static bool equal(const thread &tl, const thread &tr) noexcept;
/**
* @brief Sets the scheduling priority of a given thread.
* @param tl A valid instance of a thread.
* @param val Thread priority to set.
* @return True in case of success, false otherwise.
*/
static bool priority(const thread &tl, thread_priority val) noexcept;
/**
* @brief Retrieves the scheduling priority of a given thread.
* @param tl A valid instance of a thread.
* @return A `std::pair` composed as it follows:
* * A boolean value that is true in case of success, false otherwise.
* * The scheduled priority for the given thread.
*/
static std::pair<bool, thread_priority> priority(const thread &tl) noexcept;
~thread() noexcept; ~thread() noexcept;
/** /**
@ -157,7 +183,7 @@ public:
/** /**
* @brief Runs a function once and only once. * @brief Runs a function once and only once.
* *
* The callback must be such that it's convertible to `void(*)(void)`. Free * The callback must be such that it's convertible to `void(*)()`. Free
* functions and non-capturing lambdas are both viable solutions. * functions and non-capturing lambdas are both viable solutions.
* *
* @tparam F Type of the callback. * @tparam F Type of the callback.
@ -165,7 +191,7 @@ public:
*/ */
template<typename F> template<typename F>
static void run(F &&f) noexcept { static void run(F &&f) noexcept {
using callback_type = void (*)(void); using callback_type = void (*)();
static_assert(std::is_convertible_v<F, callback_type>); static_assert(std::is_convertible_v<F, callback_type>);
callback_type cb = f; callback_type cb = f;
uv_once(guard(), cb); uv_once(guard(), cb);
@ -355,7 +381,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "thread.cpp" # include "thread.ipp"
#endif #endif
#endif // UVW_THREAD_INCLUDE_H #endif // UVW_THREAD_INCLUDE_H

185
src/uvw/thread.ipp Normal file
View File

@ -0,0 +1,185 @@
#include "config.h"
namespace uvw {
UVW_INLINE thread::thread(loop::token token, std::shared_ptr<loop> ref, task t, std::shared_ptr<void> d) noexcept
: uv_type{token, std::move(ref)},
data{std::move(d)},
func{std::move(t)} {}
UVW_INLINE void thread::create_callback(void *arg) {
thread &curr = *(static_cast<thread *>(arg));
curr.func(curr.data);
}
UVW_INLINE thread::type thread::self() noexcept {
return uv_thread_self();
}
UVW_INLINE int thread::getcpu() noexcept {
return uv_thread_getcpu();
}
UVW_INLINE bool thread::equal(const thread &tl, const thread &tr) noexcept {
return !(0 == uv_thread_equal(tl.raw(), tr.raw()));
}
UVW_INLINE bool thread::priority(const thread &tl, thread_priority val) noexcept {
return (uv_thread_setpriority(*tl.raw(), static_cast<std::underlying_type_t<thread_priority>>(val)) == 0);
}
UVW_INLINE std::pair<bool, thread::thread_priority> thread::priority(const thread &tl) noexcept {
int prio{};
const bool res = (uv_thread_getpriority(*tl.raw(), &prio) == 0);
return {res, thread_priority{static_cast<std::underlying_type_t<thread_priority>>(prio)}};
}
UVW_INLINE thread::~thread() noexcept {
join();
}
UVW_INLINE bool thread::run() noexcept {
return (0 == uv_thread_create(raw(), &create_callback, this));
}
UVW_INLINE bool thread::run(create_flags opts, std::size_t stack) noexcept {
uv_thread_options_t params{static_cast<unsigned int>(opts), stack};
return (0 == uv_thread_create_ex(raw(), &params, &create_callback, this));
}
UVW_INLINE bool thread::join() noexcept {
return (0 == uv_thread_join(raw()));
}
UVW_INLINE thread_local_storage::thread_local_storage(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_key_create(uv_type::raw());
}
UVW_INLINE thread_local_storage::~thread_local_storage() noexcept {
uv_key_delete(uv_type::raw());
}
UVW_INLINE uv_once_t *once::guard() noexcept {
static uv_once_t once = UV_ONCE_INIT;
return &once;
}
UVW_INLINE mutex::mutex(loop::token token, std::shared_ptr<loop> ref, bool recursive) noexcept
: uv_type{token, std::move(ref)} {
if(recursive) {
uv_mutex_init_recursive(raw());
} else {
uv_mutex_init(raw());
}
}
UVW_INLINE mutex::~mutex() noexcept {
uv_mutex_destroy(raw());
}
UVW_INLINE void mutex::lock() noexcept {
uv_mutex_lock(raw());
}
UVW_INLINE bool mutex::try_lock() noexcept {
return (0 == uv_mutex_trylock(raw()));
}
UVW_INLINE void mutex::unlock() noexcept {
uv_mutex_unlock(raw());
}
UVW_INLINE rwlock::rwlock(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_rwlock_init(raw());
}
UVW_INLINE rwlock::~rwlock() noexcept {
uv_rwlock_destroy(raw());
}
UVW_INLINE void rwlock::rdlock() noexcept {
uv_rwlock_rdlock(raw());
}
UVW_INLINE bool rwlock::try_rdlock() noexcept {
return (0 == uv_rwlock_tryrdlock(raw()));
}
UVW_INLINE void rwlock::rdunlock() noexcept {
uv_rwlock_rdunlock(raw());
}
UVW_INLINE void rwlock::wrlock() noexcept {
uv_rwlock_wrlock(raw());
}
UVW_INLINE bool rwlock::try_wrlock() noexcept {
return (0 == uv_rwlock_trywrlock(raw()));
}
UVW_INLINE void rwlock::wrunlock() noexcept {
uv_rwlock_wrunlock(raw());
}
UVW_INLINE semaphore::semaphore(loop::token token, std::shared_ptr<loop> ref, unsigned int value) noexcept
: uv_type{token, std::move(ref)} {
uv_sem_init(raw(), value);
}
UVW_INLINE semaphore::~semaphore() noexcept {
uv_sem_destroy(raw());
}
UVW_INLINE void semaphore::post() noexcept {
uv_sem_post(raw());
}
UVW_INLINE void semaphore::wait() noexcept {
uv_sem_wait(raw());
}
UVW_INLINE bool semaphore::try_wait() noexcept {
return (0 == uv_sem_trywait(raw()));
}
UVW_INLINE condition::condition(loop::token token, std::shared_ptr<loop> ref) noexcept
: uv_type{token, std::move(ref)} {
uv_cond_init(raw());
}
UVW_INLINE condition::~condition() noexcept {
uv_cond_destroy(raw());
}
UVW_INLINE void condition::signal() noexcept {
uv_cond_signal(raw());
}
UVW_INLINE void condition::broadcast() noexcept {
uv_cond_broadcast(raw());
}
UVW_INLINE void condition::wait(mutex &mtx) noexcept {
uv_cond_wait(raw(), mtx.raw());
}
UVW_INLINE bool condition::timed_wait(mutex &mtx, uint64_t timeout) noexcept {
return (0 == uv_cond_timedwait(raw(), mtx.raw(), timeout));
}
UVW_INLINE barrier::barrier(loop::token token, std::shared_ptr<loop> ref, unsigned int count) noexcept
: uv_type{token, std::move(ref)} {
uv_barrier_init(raw(), count);
}
UVW_INLINE barrier::~barrier() noexcept {
uv_barrier_destroy(raw());
}
UVW_INLINE bool barrier::wait() noexcept {
return (0 == uv_barrier_wait(raw()));
}
} // namespace uvw

View File

@ -1,42 +1,2 @@
#ifdef UVW_AS_LIB #include "timer.h"
# include "timer.h" #include "timer.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE void timer_handle::start_callback(uv_timer_t *hndl) {
timer_handle &timer = *(static_cast<timer_handle *>(hndl->data));
timer.publish(timer_event{});
}
UVW_INLINE int timer_handle::init() {
return leak_if(uv_timer_init(parent().raw(), raw()));
}
UVW_INLINE int timer_handle::start(timer_handle::time timeout, timer_handle::time repeat) {
return uv_timer_start(raw(), &start_callback, timeout.count(), repeat.count());
}
UVW_INLINE int timer_handle::stop() {
return uv_timer_stop(raw());
}
UVW_INLINE int timer_handle::again() {
return uv_timer_again(raw());
}
UVW_INLINE void timer_handle::repeat(timer_handle::time repeat) {
uv_timer_set_repeat(raw(), repeat.count());
}
UVW_INLINE timer_handle::time timer_handle::repeat() {
return time{uv_timer_get_repeat(raw())};
}
UVW_INLINE timer_handle::time timer_handle::due_in() {
return time{uv_timer_get_due_in(raw())};
}
} // namespace uvw

View File

@ -1,8 +1,8 @@
#ifndef UVW_TIMER_INCLUDE_H #ifndef UVW_TIMER_INCLUDE_H
#define UVW_TIMER_INCLUDE_H #define UVW_TIMER_INCLUDE_H
#include <cstdint>
#include <chrono> #include <chrono>
#include <cstdint>
#include <uv.h> #include <uv.h>
#include "handle.hpp" #include "handle.hpp"
#include "loop.h" #include "loop.h"
@ -31,7 +31,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Starts the timer. * @brief Starts the timer.
@ -105,7 +105,7 @@ public:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "timer.cpp" # include "timer.ipp"
#endif #endif
#endif // UVW_TIMER_INCLUDE_H #endif // UVW_TIMER_INCLUDE_H

38
src/uvw/timer.ipp Normal file
View File

@ -0,0 +1,38 @@
#include "config.h"
namespace uvw {
UVW_INLINE void timer_handle::start_callback(uv_timer_t *hndl) {
timer_handle &timer = *(static_cast<timer_handle *>(hndl->data));
timer.publish(timer_event{});
}
UVW_INLINE int timer_handle::init() {
return leak_if(uv_timer_init(parent().raw(), raw()));
}
UVW_INLINE int timer_handle::start(timer_handle::time timeout, timer_handle::time repeat) {
return uv_timer_start(raw(), &start_callback, timeout.count(), repeat.count());
}
UVW_INLINE int timer_handle::stop() {
return uv_timer_stop(raw());
}
UVW_INLINE int timer_handle::again() {
return uv_timer_again(raw());
}
UVW_INLINE void timer_handle::repeat(timer_handle::time repeat) {
uv_timer_set_repeat(raw(), repeat.count());
}
UVW_INLINE timer_handle::time timer_handle::repeat() {
return time{uv_timer_get_repeat(raw())};
}
UVW_INLINE timer_handle::time timer_handle::due_in() {
return time{uv_timer_get_due_in(raw())};
}
} // namespace uvw

View File

@ -1,67 +1,2 @@
#ifdef UVW_AS_LIB #include "tty.h"
# include "tty.h" #include "tty.ipp"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE details::reset_mode_memo::~reset_mode_memo() {
uv_tty_reset_mode();
}
UVW_INLINE tty_handle::tty_handle(loop::token token, std::shared_ptr<loop> ref, file_handle desc, bool readable)
: stream_handle{token, std::move(ref)},
memo{mode_memo_handler()},
fd{desc},
rw{readable} {}
UVW_INLINE std::shared_ptr<details::reset_mode_memo> tty_handle::mode_memo_handler() {
static std::weak_ptr<details::reset_mode_memo> weak;
auto shared = weak.lock();
if(!shared) { weak = shared = std::make_shared<details::reset_mode_memo>(); }
return shared;
};
UVW_INLINE int tty_handle::init() {
return leak_if(uv_tty_init(parent().raw(), raw(), fd, rw));
}
UVW_INLINE bool tty_handle::mode(tty_handle::tty_mode m) {
return (0 == uv_tty_set_mode(raw(), static_cast<uv_tty_mode_t>(m)));
}
UVW_INLINE bool tty_handle::reset_mode() noexcept {
return (0 == uv_tty_reset_mode());
}
UVW_INLINE win_size tty_handle::get_win_size() {
win_size size;
if(0 != uv_tty_get_winsize(raw(), &size.width, &size.height)) {
size.width = -1;
size.height = -1;
}
return size;
}
UVW_INLINE void tty_handle::vterm_state(tty_handle::tty_vtermstate s) const noexcept {
switch(s) {
case tty_vtermstate::SUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_SUPPORTED);
break;
case tty_vtermstate::UNSUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_UNSUPPORTED);
break;
}
}
UVW_INLINE tty_handle::tty_vtermstate tty_handle::vterm_state() const noexcept {
uv_tty_vtermstate_t state;
uv_tty_get_vterm_state(&state);
return tty_vtermstate{state};
}
} // namespace uvw

View File

@ -60,7 +60,7 @@ public:
* @brief Initializes the handle. * @brief Initializes the handle.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Sets the TTY using the specified terminal mode. * @brief Sets the TTY using the specified terminal mode.
@ -140,7 +140,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "tty.cpp" # include "tty.ipp"
#endif #endif
#endif // UVW_TTY_INCLUDE_H #endif // UVW_TTY_INCLUDE_H

65
src/uvw/tty.ipp Normal file
View File

@ -0,0 +1,65 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE details::reset_mode_memo::~reset_mode_memo() {
uv_tty_reset_mode();
}
UVW_INLINE tty_handle::tty_handle(loop::token token, std::shared_ptr<loop> ref, file_handle desc, bool readable)
: stream_handle{token, std::move(ref)},
memo{mode_memo_handler()},
fd{desc},
rw{readable} {}
UVW_INLINE std::shared_ptr<details::reset_mode_memo> tty_handle::mode_memo_handler() {
static std::weak_ptr<details::reset_mode_memo> weak;
auto shared = weak.lock();
if(!shared) {
weak = shared = std::make_shared<details::reset_mode_memo>();
}
return shared;
}
UVW_INLINE int tty_handle::init() {
return leak_if(uv_tty_init(parent().raw(), raw(), fd, rw));
}
UVW_INLINE bool tty_handle::mode(tty_handle::tty_mode m) {
return (0 == uv_tty_set_mode(raw(), static_cast<uv_tty_mode_t>(m)));
}
UVW_INLINE bool tty_handle::reset_mode() noexcept {
return (0 == uv_tty_reset_mode());
}
UVW_INLINE win_size tty_handle::get_win_size() {
win_size size;
if(0 != uv_tty_get_winsize(raw(), &size.width, &size.height)) {
size.width = -1;
size.height = -1;
}
return size;
}
UVW_INLINE void tty_handle::vterm_state(tty_handle::tty_vtermstate s) const noexcept {
switch(s) {
case tty_vtermstate::SUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_SUPPORTED);
break;
case tty_vtermstate::UNSUPPORTED:
uv_tty_set_vterm_state(uv_tty_vtermstate_t::UV_TTY_UNSUPPORTED);
break;
}
}
UVW_INLINE tty_handle::tty_vtermstate tty_handle::vterm_state() const noexcept {
uv_tty_vtermstate_t state;
uv_tty_get_vterm_state(&state);
return tty_vtermstate{state};
}
} // namespace uvw

View File

@ -2,6 +2,7 @@
#define UVW_TYPE_INFO_INCLUDE_HPP #define UVW_TYPE_INFO_INCLUDE_HPP
#include <cstdint> #include <cstdint>
#include <string_view>
#include "config.h" #include "config.h"
namespace uvw { namespace uvw {
@ -14,13 +15,13 @@ namespace uvw {
namespace internal { namespace internal {
// Fowler-Noll-Vo hash function v. 1a - the good // Fowler-Noll-Vo hash function v. 1a - the good
[[nodiscard]] static constexpr std::uint32_t fnv1a(const char *curr) noexcept { [[nodiscard]] static constexpr std::uint32_t fnv1a(const std::string_view view) noexcept {
constexpr std::uint32_t offset = 2166136261; constexpr std::uint32_t offset = 2166136261;
constexpr std::uint32_t prime = 16777619; constexpr std::uint32_t prime = 16777619;
auto value = offset; auto value = offset;
while(*curr != 0) { for(auto &&curr: view) {
value = (value ^ static_cast<std::uint32_t>(*(curr++))) * prime; value = (value ^ static_cast<std::uint32_t>(static_cast<unsigned char>(curr))) * prime;
} }
return value; return value;

View File

@ -1,216 +1,2 @@
#ifdef UVW_AS_LIB #include "udp.h"
# include "udp.h" #include "udp.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE udp_data_event::udp_data_event(socket_address sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept
: data{std::move(buf)},
length{len},
sender{std::move(sndr)},
partial{part} {}
UVW_INLINE void details::send_req::udp_send_callback(uv_udp_send_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(send_event{});
}
}
UVW_INLINE details::send_req::send_req(loop::token token, std::shared_ptr<loop> parent, std::unique_ptr<char[], deleter> dt, unsigned int len)
: request{token, std::move(parent)},
data{std::move(dt)},
buf{uv_buf_init(data.get(), len)} {}
UVW_INLINE int details::send_req::send(uv_udp_t *hndl, const struct sockaddr *addr) {
return this->leak_if(uv_udp_send(raw(), hndl, &buf, 1, addr, &udp_send_callback));
}
UVW_INLINE void udp_handle::recv_callback(uv_udp_t *hndl, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
udp_handle &udp = *(static_cast<udp_handle *>(hndl->data));
// data will be destroyed no matter of what the value of nread is
std::unique_ptr<char[]> data{buf->base};
if(nread > 0) {
// data available (can be truncated)
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
} else if(nread == 0 && addr == nullptr) {
// no more data to be read, doing nothing is fine
} else if(nread == 0 && addr != nullptr) {
// empty udp packet
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), false});
} else {
// transmission error
udp.publish(error_event(nread));
}
}
UVW_INLINE udp_handle::udp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: handle{token, std::move(ref)}, tag{FLAGS}, flags{f} {}
UVW_INLINE int udp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_udp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_udp_init(parent().raw(), raw()));
}
}
UVW_INLINE int udp_handle::open(os_socket_handle socket) {
return uv_udp_open(raw(), socket);
}
UVW_INLINE int udp_handle::connect(const sockaddr &addr) {
return uv_udp_connect(raw(), &addr);
}
UVW_INLINE int udp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int udp_handle::connect(socket_address addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int udp_handle::disconnect() {
return uv_udp_connect(raw(), nullptr);
}
UVW_INLINE socket_address udp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int udp_handle::bind(const sockaddr &addr, udp_handle::udp_flags opts) {
return uv_udp_bind(raw(), &addr, static_cast<uv_udp_flags>(opts));
}
UVW_INLINE int udp_handle::bind(const std::string &ip, unsigned int port, udp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int udp_handle::bind(socket_address addr, udp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address udp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE bool udp_handle::multicast_membership(const std::string &multicast, const std::string &iface, membership ms) {
return (0 == uv_udp_set_membership(raw(), multicast.data(), iface.data(), static_cast<uv_membership>(ms)));
}
UVW_INLINE bool udp_handle::multicast_loop(bool enable) {
return (0 == uv_udp_set_multicast_loop(raw(), enable));
}
UVW_INLINE bool udp_handle::multicast_ttl(int val) {
return (0 == uv_udp_set_multicast_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE bool udp_handle::multicast_interface(const std::string &iface) {
return (0 == uv_udp_set_multicast_interface(raw(), iface.data()));
}
UVW_INLINE bool udp_handle::broadcast(bool enable) {
return (0 == uv_udp_set_broadcast(raw(), enable));
}
UVW_INLINE bool udp_handle::ttl(int val) {
return (0 == uv_udp_set_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data.release(), [](char *ptr) { delete[] ptr; }}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len) {
return send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, char *data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data, [](char *) {}}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::send(socket_address addr, char *data, unsigned int len) {
return send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data.get(), len)};
return uv_udp_try_send(raw(), bufs, 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, char *data, unsigned int len) {
uv_buf_t bufs[] = {uv_buf_init(data, len)};
return uv_udp_try_send(raw(), bufs, 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::try_send(socket_address addr, char *data, unsigned int len) {
return try_send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::recv() {
return uv_udp_recv_start(raw(), &details::common_alloc_callback, &recv_callback);
}
UVW_INLINE int udp_handle::stop() {
return uv_udp_recv_stop(raw());
}
UVW_INLINE size_t udp_handle::send_queue_size() const noexcept {
return uv_udp_get_send_queue_size(raw());
}
UVW_INLINE size_t udp_handle::send_queue_count() const noexcept {
return uv_udp_get_send_queue_count(raw());
}
} // namespace uvw

View File

@ -38,7 +38,7 @@ enum class uvw_udp_flags : std::underlying_type_t<uv_udp_flags> {
UDP_MMSG_FREE = UV_UDP_MMSG_FREE, UDP_MMSG_FREE = UV_UDP_MMSG_FREE,
UDP_LINUX_RECVERR = UV_UDP_LINUX_RECVERR, UDP_LINUX_RECVERR = UV_UDP_LINUX_RECVERR,
UDP_RECVMMSG = UV_UDP_RECVMMSG, UDP_RECVMMSG = UV_UDP_RECVMMSG,
_UVW_ENUM = 0 UVW_ENUM = 0
}; };
enum class uvw_membership : std::underlying_type_t<uv_membership> { enum class uvw_membership : std::underlying_type_t<uv_membership> {
@ -94,7 +94,7 @@ public:
* @brief Initializes the handle. The actual socket is created lazily. * @brief Initializes the handle. The actual socket is created lazily.
* @return Underlying return value. * @return Underlying return value.
*/ */
int init() final; int init();
/** /**
* @brief Opens an existing file descriptor or SOCKET as a UDP handle. * @brief Opens an existing file descriptor or SOCKET as a UDP handle.
@ -154,7 +154,7 @@ public:
* @param addr A valid instance of socket_address. * @param addr A valid instance of socket_address.
* @return Underlying return value. * @return Underlying return value.
*/ */
int connect(socket_address addr); int connect(const socket_address &addr);
/** /**
* @brief Disconnects the handle. * @brief Disconnects the handle.
@ -193,7 +193,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(const sockaddr &addr, udp_flags opts = udp_flags::_UVW_ENUM); int bind(const sockaddr &addr, udp_flags opts = udp_flags::UVW_ENUM);
/** /**
* @brief Binds the UDP handle to an IP address and port. * @brief Binds the UDP handle to an IP address and port.
@ -217,7 +217,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(const std::string &ip, unsigned int port, udp_flags opts = udp_flags::_UVW_ENUM); int bind(const std::string &ip, unsigned int port, udp_flags opts = udp_flags::UVW_ENUM);
/** /**
* @brief Binds the UDP handle to an IP address and port. * @brief Binds the UDP handle to an IP address and port.
@ -240,7 +240,7 @@ public:
* @param opts Optional additional flags. * @param opts Optional additional flags.
* @return Underlying return value. * @return Underlying return value.
*/ */
int bind(socket_address addr, udp_flags opts = udp_flags::_UVW_ENUM); int bind(const socket_address &addr, udp_flags opts = udp_flags::UVW_ENUM);
/** /**
* @brief Get the local IP and port of the UDP handle. * @brief Get the local IP and port of the UDP handle.
@ -358,7 +358,7 @@ public:
* @param len The lenght of the submitted data. * @param len The lenght of the submitted data.
* @return Underlying return value. * @return Underlying return value.
*/ */
int send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len); int send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len);
/** /**
* @brief Sends data over the UDP socket. * @brief Sends data over the UDP socket.
@ -416,7 +416,7 @@ public:
* @param len The lenght of the submitted data. * @param len The lenght of the submitted data.
* @return Underlying return value. * @return Underlying return value.
*/ */
int send(socket_address addr, char *data, unsigned int len); int send(const socket_address &addr, char *data, unsigned int len);
/** /**
* @brief Sends data over the UDP socket. * @brief Sends data over the UDP socket.
@ -456,7 +456,7 @@ public:
* @param len The lenght of the submitted data. * @param len The lenght of the submitted data.
* @return Underlying return value. * @return Underlying return value.
*/ */
int try_send(socket_address addr, std::unique_ptr<char[]> data, unsigned int len); int try_send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len);
/** /**
* @brief Sends data over the UDP socket. * @brief Sends data over the UDP socket.
@ -496,7 +496,7 @@ public:
* @param len The lenght of the submitted data. * @param len The lenght of the submitted data.
* @return Underlying return value. * @return Underlying return value.
*/ */
int try_send(socket_address addr, char *data, unsigned int len); int try_send(const socket_address &addr, char *data, unsigned int len);
/** /**
* @brief Prepares for receiving data. * @brief Prepares for receiving data.
@ -556,7 +556,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "udp.cpp" # include "udp.ipp"
#endif #endif
#endif // UVW_UDP_INCLUDE_H #endif // UVW_UDP_INCLUDE_H

213
src/uvw/udp.ipp Normal file
View File

@ -0,0 +1,213 @@
#include <array>
#include "config.h"
namespace uvw {
UVW_INLINE udp_data_event::udp_data_event(socket_address sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept
: data{std::move(buf)},
length{len},
sender{std::move(sndr)},
partial{part} {}
UVW_INLINE void details::send_req::udp_send_callback(uv_udp_send_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(send_event{});
}
}
UVW_INLINE details::send_req::send_req(loop::token token, std::shared_ptr<loop> parent, std::unique_ptr<char[], deleter> dt, unsigned int len)
: request{token, std::move(parent)},
data{std::move(dt)},
buf{uv_buf_init(data.get(), len)} {}
UVW_INLINE int details::send_req::send(uv_udp_t *hndl, const struct sockaddr *addr) {
return this->leak_if(uv_udp_send(raw(), hndl, &buf, 1, addr, &udp_send_callback));
}
UVW_INLINE void udp_handle::recv_callback(uv_udp_t *hndl, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
udp_handle &udp = *(static_cast<udp_handle *>(hndl->data));
// data will be destroyed no matter of what the value of nread is
std::unique_ptr<char[]> data{buf->base};
if(nread > 0) {
// data available (can be truncated)
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
} else if(nread == 0 && addr == nullptr) {
// no more data to be read, doing nothing is fine
} else if(nread == 0 && addr != nullptr) {
// empty udp packet
udp.publish(udp_data_event{details::sock_addr(*addr), std::move(data), static_cast<std::size_t>(nread), false});
} else {
// transmission error
udp.publish(error_event(nread));
}
}
UVW_INLINE udp_handle::udp_handle(loop::token token, std::shared_ptr<loop> ref, unsigned int f)
: handle{token, std::move(ref)}, tag{FLAGS}, flags{f} {}
UVW_INLINE int udp_handle::init() {
if(tag == FLAGS) {
return leak_if(uv_udp_init_ex(parent().raw(), raw(), flags));
} else {
return leak_if(uv_udp_init(parent().raw(), raw()));
}
}
UVW_INLINE int udp_handle::open(os_socket_handle socket) {
return uv_udp_open(raw(), socket);
}
UVW_INLINE int udp_handle::connect(const sockaddr &addr) {
return uv_udp_connect(raw(), &addr);
}
UVW_INLINE int udp_handle::connect(const std::string &ip, unsigned int port) {
return connect(details::ip_addr(ip.data(), port));
}
UVW_INLINE int udp_handle::connect(const socket_address &addr) {
return connect(addr.ip, addr.port);
}
UVW_INLINE int udp_handle::disconnect() {
return uv_udp_connect(raw(), nullptr);
}
UVW_INLINE socket_address udp_handle::peer() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getpeername(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE int udp_handle::bind(const sockaddr &addr, udp_handle::udp_flags opts) {
return uv_udp_bind(raw(), &addr, static_cast<uv_udp_flags>(opts));
}
UVW_INLINE int udp_handle::bind(const std::string &ip, unsigned int port, udp_flags opts) {
return bind(details::ip_addr(ip.data(), port), opts);
}
UVW_INLINE int udp_handle::bind(const socket_address &addr, udp_flags opts) {
return bind(addr.ip, addr.port, opts);
}
UVW_INLINE socket_address udp_handle::sock() const noexcept {
sockaddr_storage storage;
int len = sizeof(sockaddr_storage);
uv_udp_getsockname(raw(), reinterpret_cast<sockaddr *>(&storage), &len);
return details::sock_addr(storage);
}
UVW_INLINE bool udp_handle::multicast_membership(const std::string &multicast, const std::string &iface, membership ms) {
return (0 == uv_udp_set_membership(raw(), multicast.data(), iface.data(), static_cast<uv_membership>(ms)));
}
UVW_INLINE bool udp_handle::multicast_loop(bool enable) {
return (0 == uv_udp_set_multicast_loop(raw(), enable));
}
UVW_INLINE bool udp_handle::multicast_ttl(int val) {
return (0 == uv_udp_set_multicast_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE bool udp_handle::multicast_interface(const std::string &iface) {
return (0 == uv_udp_set_multicast_interface(raw(), iface.data()));
}
UVW_INLINE bool udp_handle::broadcast(bool enable) {
return (0 == uv_udp_set_broadcast(raw(), enable));
}
UVW_INLINE bool udp_handle::ttl(int val) {
return (0 == uv_udp_set_ttl(raw(), val > 255 ? 255 : val));
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data.release(), [](char *ptr) { delete[] ptr; }}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len) {
return send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::send(const sockaddr &addr, char *data, unsigned int len) {
auto req = parent().resource<details::send_req>(std::unique_ptr<char[], details::send_req::deleter>{data, [](char *) {}}, len);
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
ptr->publish(event);
};
req->on<error_event>(listener);
req->on<send_event>(listener);
return req->send(raw(), &addr);
}
UVW_INLINE int udp_handle::send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::send(const socket_address &addr, char *data, unsigned int len) {
return send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
std::array bufs{uv_buf_init(data.get(), len)};
return uv_udp_try_send(raw(), bufs.data(), 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const socket_address &addr, std::unique_ptr<char[]> data, unsigned int len) {
return try_send(addr.ip, addr.port, std::move(data), len);
}
UVW_INLINE int udp_handle::try_send(const sockaddr &addr, char *data, unsigned int len) {
std::array bufs{uv_buf_init(data, len)};
return uv_udp_try_send(raw(), bufs.data(), 1, &addr);
}
UVW_INLINE int udp_handle::try_send(const std::string &ip, unsigned int port, char *data, unsigned int len) {
return try_send(details::ip_addr(ip.data(), port), data, len);
}
UVW_INLINE int udp_handle::try_send(const socket_address &addr, char *data, unsigned int len) {
return try_send(addr.ip, addr.port, data, len);
}
UVW_INLINE int udp_handle::recv() {
return uv_udp_recv_start(raw(), &details::common_alloc_callback, &recv_callback);
}
UVW_INLINE int udp_handle::stop() {
return uv_udp_recv_stop(raw());
}
UVW_INLINE size_t udp_handle::send_queue_size() const noexcept {
return uv_udp_get_send_queue_size(raw());
}
UVW_INLINE size_t udp_handle::send_queue_count() const noexcept {
return uv_udp_get_send_queue_count(raw());
}
} // namespace uvw

View File

@ -1,365 +1,2 @@
#ifdef UVW_AS_LIB #include "util.h"
# include "util.h" #include "util.ipp"
#endif
#include "config.h"
namespace uvw {
UVW_INLINE passwd_info::passwd_info(std::shared_ptr<uv_passwd_t> pwd)
: value{pwd} {}
UVW_INLINE std::string passwd_info::username() const noexcept {
return ((value && value->username) ? value->username : "");
}
UVW_INLINE decltype(uv_passwd_t::uid) passwd_info::uid() const noexcept {
return (value ? value->uid : decltype(uv_passwd_t::uid){});
}
UVW_INLINE decltype(uv_passwd_t::gid) passwd_info::gid() const noexcept {
return (value ? value->gid : decltype(uv_passwd_t::gid){});
}
UVW_INLINE std::string passwd_info::shell() const noexcept {
return ((value && value->shell) ? value->shell : "");
}
UVW_INLINE std::string passwd_info::homedir() const noexcept {
return ((value && value->homedir) ? value->homedir : "");
}
UVW_INLINE passwd_info::operator bool() const noexcept {
return static_cast<bool>(value);
}
UVW_INLINE uts_name::uts_name(std::shared_ptr<uv_utsname_t> init)
: uname{init} {}
UVW_INLINE std::string uts_name::sysname() const noexcept {
return uname ? uname->sysname : "";
}
UVW_INLINE std::string uts_name::release() const noexcept {
return uname ? uname->release : "";
}
UVW_INLINE std::string uts_name::version() const noexcept {
return uname ? uname->version : "";
}
UVW_INLINE std::string uts_name::machine() const noexcept {
return uname ? uname->machine : "";
}
namespace details {
UVW_INLINE void common_alloc_callback(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);
}
UVW_INLINE sockaddr ip_addr(const char *addr, unsigned int port) {
if(sockaddr_in addr_in; uv_ip4_addr(addr, port, &addr_in) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in);
} else if(sockaddr_in6 addr_in6; uv_ip6_addr(addr, port, &addr_in6) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in6);
}
return {};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in &addr) {
if(char name[details::DEFAULT_SIZE]; uv_ip4_name(&addr, name, details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name}, ntohs(addr.sin_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in6 &addr) {
if(char name[details::DEFAULT_SIZE]; uv_ip6_name(&addr, name, details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name}, ntohs(addr.sin6_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr &addr) {
if(addr.sa_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(addr));
} else if(addr.sa_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(addr));
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_storage &storage) {
if(storage.ss_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(storage));
} else if(storage.ss_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(storage));
}
return socket_address{};
}
} // namespace details
UVW_INLINE pid_type utilities::os::pid() noexcept {
return uv_os_getpid();
}
UVW_INLINE pid_type utilities::os::ppid() noexcept {
return uv_os_getppid();
}
UVW_INLINE std::string utilities::os::homedir() noexcept {
return details::try_read(&uv_os_homedir);
}
UVW_INLINE std::string utilities::os::tmpdir() noexcept {
return details::try_read(&uv_os_tmpdir);
}
UVW_INLINE std::string utilities::os::env(const std::string &name) noexcept {
return details::try_read(&uv_os_getenv, name.c_str());
}
UVW_INLINE bool utilities::os::env(const std::string &name, const std::string &value) noexcept {
return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
}
UVW_INLINE std::string utilities::os::hostname() noexcept {
return details::try_read(&uv_os_gethostname);
}
UVW_INLINE uts_name utilities::os::uname() noexcept {
auto ptr = std::make_shared<uv_utsname_t>();
uv_os_uname(ptr.get());
return ptr;
}
UVW_INLINE passwd_info utilities::os::passwd() noexcept {
auto deleter = [](uv_passwd_t *passwd) {
uv_os_free_passwd(passwd);
delete passwd;
};
std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
uv_os_get_passwd(ptr.get());
return ptr;
}
UVW_INLINE int utilities::os::priority(pid_type pid) {
int prio = 0;
if(uv_os_getpriority(pid, &prio)) {
prio = UV_PRIORITY_LOW + 1;
}
return prio;
}
UVW_INLINE bool utilities::os::priority(pid_type pid, int prio) {
return 0 == uv_os_setpriority(pid, prio);
}
UVW_INLINE handle_type utilities::guess_handle(handle_category category) noexcept {
switch(category) {
case UV_ASYNC:
return handle_type::ASYNC;
case UV_CHECK:
return handle_type::CHECK;
case UV_FS_EVENT:
return handle_type::FS_EVENT;
case UV_FS_POLL:
return handle_type::FS_POLL;
case UV_HANDLE:
return handle_type::HANDLE;
case UV_IDLE:
return handle_type::IDLE;
case UV_NAMED_PIPE:
return handle_type::PIPE;
case UV_POLL:
return handle_type::POLL;
case UV_PREPARE:
return handle_type::PREPARE;
case UV_PROCESS:
return handle_type::PROCESS;
case UV_STREAM:
return handle_type::STREAM;
case UV_TCP:
return handle_type::TCP;
case UV_TIMER:
return handle_type::TIMER;
case UV_TTY:
return handle_type::TTY;
case UV_UDP:
return handle_type::UDP;
case UV_SIGNAL:
return handle_type::SIGNAL;
case UV_FILE:
return handle_type::FILE;
default:
return handle_type::UNKNOWN;
}
}
UVW_INLINE handle_type utilities::guess_handle(file_handle file) noexcept {
handle_category category = uv_guess_handle(file);
return guess_handle(category);
}
UVW_INLINE std::vector<cpu_info> utilities::cpu() noexcept {
std::vector<cpu_info> cpuinfos;
uv_cpu_info_t *infos;
int count;
if(0 == uv_cpu_info(&infos, &count)) {
for(int next = 0; next < count; ++next) {
cpuinfos.push_back({infos[next].model, infos[next].speed, infos[next].cpu_times});
}
uv_free_cpu_info(infos, count);
}
return cpuinfos;
}
UVW_INLINE std::vector<interface_address> utilities::interface_addresses() noexcept {
std::vector<interface_address> interfaces;
uv_interface_address_t *ifaces{nullptr};
int count{0};
if(0 == uv_interface_addresses(&ifaces, &count)) {
for(int next = 0; next < count; ++next) {
interface_address iface_addr;
iface_addr.name = ifaces[next].name;
std::copy(ifaces[next].phys_addr, (ifaces[next].phys_addr + 6), iface_addr.physical);
iface_addr.internal = ifaces[next].is_internal == 0 ? false : true;
if(ifaces[next].address.address4.sin_family == AF_INET) {
iface_addr.address = details::sock_addr(ifaces[next].address.address4);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask4);
} else if(ifaces[next].address.address4.sin_family == AF_INET6) {
iface_addr.address = details::sock_addr(ifaces[next].address.address6);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask6);
}
interfaces.push_back(std::move(iface_addr));
}
uv_free_interface_addresses(ifaces, count);
}
return interfaces;
}
UVW_INLINE std::string utilities::index_to_name(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoname, index);
}
UVW_INLINE std::string utilities::index_to_iid(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoiid, index);
}
UVW_INLINE bool utilities::replace_allocator(malloc_func_type malloc_func, realloc_func_type realloc_func, calloc_func_type calloc_func, free_func_type free_func) noexcept {
return (0 == uv_replace_allocator(malloc_func, realloc_func, calloc_func, free_func));
}
UVW_INLINE std::array<double, 3> utilities::load_average() noexcept {
std::array<double, 3> avg;
uv_loadavg(avg.data());
return avg;
}
UVW_INLINE char **utilities::setup_args(int argc, char **argv) {
return uv_setup_args(argc, argv);
}
UVW_INLINE std::string utilities::process_title() {
std::size_t size = details::DEFAULT_SIZE;
char buf[details::DEFAULT_SIZE];
std::string str{};
if(0 == uv_get_process_title(buf, size)) {
str.assign(buf, size);
}
return str;
}
UVW_INLINE bool utilities::process_title(const std::string &title) {
return (0 == uv_set_process_title(title.c_str()));
}
UVW_INLINE uint64_t utilities::total_memory() noexcept {
return uv_get_total_memory();
}
UVW_INLINE uint64_t utilities::constrained_memory() noexcept {
return uv_get_constrained_memory();
}
UVW_INLINE uint64_t utilities::available_memory() noexcept {
return uv_get_available_memory();
}
UVW_INLINE double utilities::uptime() noexcept {
double ret;
if(0 != uv_uptime(&ret)) {
ret = 0;
}
return ret;
}
UVW_INLINE resource_usage utilities::rusage() noexcept {
resource_usage ru;
auto err = uv_getrusage(&ru);
return err ? resource_usage{} : ru;
}
UVW_INLINE timespec64 utilities::gettime(clock_id source) noexcept {
timespec64 ts;
auto err = uv_clock_gettime(static_cast<uv_clock_id>(source), &ts);
return err ? timespec64{} : ts;
}
UVW_INLINE uint64_t utilities::hrtime() noexcept {
return uv_hrtime();
}
UVW_INLINE std::string utilities::path() noexcept {
return details::try_read(&uv_exepath);
}
UVW_INLINE std::string utilities::cwd() noexcept {
return details::try_read(&uv_cwd);
}
UVW_INLINE bool utilities::chdir(const std::string &dir) noexcept {
return (0 == uv_chdir(dir.data()));
}
UVW_INLINE timeval64 utilities::time_of_day() noexcept {
uv_timeval64_t ret;
uv_gettimeofday(&ret);
return ret;
}
UVW_INLINE void utilities::sleep(unsigned int msec) noexcept {
uv_sleep(msec);
}
UVW_INLINE unsigned int utilities::available_parallelism() noexcept {
return uv_available_parallelism();
}
} // namespace uvw

View File

@ -118,31 +118,31 @@ struct passwd_info {
* @brief Gets the username. * @brief Gets the username.
* @return The username of the current effective uid (not the real uid). * @return The username of the current effective uid (not the real uid).
*/ */
std::string username() const noexcept; [[nodiscard]] std::string username() const noexcept;
/** /**
* @brief Gets the uid. * @brief Gets the uid.
* @return The current effective uid (not the real uid). * @return The current effective uid (not the real uid).
*/ */
decltype(uv_passwd_t::uid) uid() const noexcept; [[nodiscard]] decltype(uv_passwd_t::uid) uid() const noexcept;
/** /**
* @brief Gets the gid. * @brief Gets the gid.
* @return The gid of the current effective uid (not the real uid). * @return The gid of the current effective uid (not the real uid).
*/ */
decltype(uv_passwd_t::gid) gid() const noexcept; [[nodiscard]] decltype(uv_passwd_t::gid) gid() const noexcept;
/** /**
* @brief Gets the shell. * @brief Gets the shell.
* @return The shell of the current effective uid (not the real uid). * @return The shell of the current effective uid (not the real uid).
*/ */
std::string shell() const noexcept; [[nodiscard]] std::string shell() const noexcept;
/** /**
* @brief Gets the homedir. * @brief Gets the homedir.
* @return The homedir of the current effective uid (not the real uid). * @return The homedir of the current effective uid (not the real uid).
*/ */
std::string homedir() const noexcept; [[nodiscard]] std::string homedir() const noexcept;
/** /**
* @brief Checks if the instance contains valid data. * @brief Checks if the instance contains valid data.
@ -170,25 +170,25 @@ struct uts_name {
* @brief Gets the operating system name (like "Linux"). * @brief Gets the operating system name (like "Linux").
* @return The operating system name. * @return The operating system name.
*/ */
std::string sysname() const noexcept; [[nodiscard]] std::string sysname() const noexcept;
/** /**
* @brief Gets the operating system release (like "2.6.28"). * @brief Gets the operating system release (like "2.6.28").
* @return The operating system release. * @return The operating system release.
*/ */
std::string release() const noexcept; [[nodiscard]] std::string release() const noexcept;
/** /**
* @brief Gets the operating system version. * @brief Gets the operating system version.
* @return The operating system version * @return The operating system version
*/ */
std::string version() const noexcept; [[nodiscard]] std::string version() const noexcept;
/** /**
* @brief Gets the hardware identifier. * @brief Gets the hardware identifier.
* @return The hardware identifier. * @return The hardware identifier.
*/ */
std::string machine() const noexcept; [[nodiscard]] std::string machine() const noexcept;
private: private:
std::shared_ptr<uv_utsname_t> uname; std::shared_ptr<uv_utsname_t> uname;
@ -238,11 +238,11 @@ struct cpu_info {
* \brief Interface address. * \brief Interface address.
*/ */
struct interface_address { struct interface_address {
std::string name; /*!< The name of the interface (as an example _eth0_). */ std::string name; /*!< The name of the interface (as an example _eth0_). */
char physical[6]; /*!< The physical address. */ std::array<char, 6u> physical; /*!< The physical address. */
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */ bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
socket_address address; /*!< The address of the given interface. */ socket_address address; /*!< The address of the given interface. */
socket_address netmask; /*!< The netmask of the given interface. */ socket_address netmask; /*!< The netmask of the given interface. */
}; };
namespace details { namespace details {
@ -250,21 +250,21 @@ namespace details {
static constexpr std::size_t DEFAULT_SIZE = 128; static constexpr std::size_t DEFAULT_SIZE = 128;
template<typename F, typename... Args> template<typename F, typename... Args>
std::string try_read(F &&f, Args &&...args) noexcept { [[nodiscard]] std::string try_read(F &&f, Args &&...args) {
std::size_t size = DEFAULT_SIZE; std::size_t size = DEFAULT_SIZE;
char buf[DEFAULT_SIZE]; std::array<char, DEFAULT_SIZE> buf{};
std::string str{}; std::string str{};
auto err = std::forward<F>(f)(args..., buf, &size); auto err = std::forward<F>(f)(args..., buf.data(), &size);
if(UV_ENOBUFS == err) { if(UV_ENOBUFS == err) {
std::unique_ptr<char[]> data{new char[size]}; auto data = std::make_unique<char[]>(size);
err = std::forward<F>(f)(args..., data.get(), &size); err = std::forward<F>(f)(args..., data.get(), &size);
if(0 == err) { if(0 == err) {
str = data.get(); str = data.get();
} }
} else if(0 == err) { } else if(0 == err) {
str.assign(buf, size); str.assign(buf.data(), size);
} }
return str; return str;
@ -310,7 +310,7 @@ struct utilities {
* *
* @return The current process id. * @return The current process id.
*/ */
static pid_type pid() noexcept; [[nodiscard]] static pid_type pid() noexcept;
/** /**
* @brief Returns the parent process id. * @brief Returns the parent process id.
@ -321,7 +321,7 @@ struct utilities {
* *
* @return The parent process id. * @return The parent process id.
*/ */
static pid_type ppid() noexcept; [[nodiscard]] static pid_type ppid() noexcept;
/** /**
* @brief Gets the current user's home directory. * @brief Gets the current user's home directory.
@ -333,7 +333,7 @@ struct utilities {
* @return The current user's home directory, an empty string in case of * @return The current user's home directory, an empty string in case of
* errors. * errors.
*/ */
static std::string homedir() noexcept; [[nodiscard]] static std::string homedir() noexcept;
/** /**
* @brief Gets the temp directory. * @brief Gets the temp directory.
@ -344,7 +344,7 @@ struct utilities {
* *
* @return The temp directory, an empty string in case of errors. * @return The temp directory, an empty string in case of errors.
*/ */
static std::string tmpdir() noexcept; [[nodiscard]] static std::string tmpdir() noexcept;
/** /**
* @brief Retrieves an environment variable. * @brief Retrieves an environment variable.
@ -352,7 +352,7 @@ struct utilities {
* @return The value of the environment variable, an empty string in * @return The value of the environment variable, an empty string in
* case of errors. * case of errors.
*/ */
static std::string env(const std::string &name) noexcept; [[nodiscard]] static std::string env(const std::string &name) noexcept;
/** /**
* @brief Creates, updates or deletes an environment variable. * @brief Creates, updates or deletes an environment variable.
@ -377,7 +377,7 @@ struct utilities {
* @return True in case of success, false otherwise. * @return True in case of success, false otherwise.
*/ */
template<typename Func> template<typename Func>
static std::enable_if_t<std::is_invocable_v<Func, std::string_view, std::string_view>, bool> [[nodiscard]] static std::enable_if_t<std::is_invocable_v<Func, std::string_view, std::string_view>, bool>
env(Func func) noexcept { env(Func func) noexcept {
uv_env_item_t *items = nullptr; uv_env_item_t *items = nullptr;
int count{}; int count{};
@ -399,7 +399,7 @@ struct utilities {
* @brief Returns the hostname. * @brief Returns the hostname.
* @return The hostname, an empty string in case of errors. * @return The hostname, an empty string in case of errors.
*/ */
static std::string hostname() noexcept; [[nodiscard]] static std::string hostname() noexcept;
/** /**
* @brief Gets name and information about the current kernel. * @brief Gets name and information about the current kernel.
@ -410,7 +410,7 @@ struct utilities {
* *
* @return Name and information about the current kernel. * @return Name and information about the current kernel.
*/ */
static uts_name uname() noexcept; [[nodiscard]] static uts_name uname() noexcept;
/** /**
* @brief Gets a subset of the password file entry. * @brief Gets a subset of the password file entry.
@ -424,7 +424,7 @@ struct utilities {
* *
* @return The accessible subset of the password file entry. * @return The accessible subset of the password file entry.
*/ */
static passwd_info passwd() noexcept; [[nodiscard]] static passwd_info passwd();
/** /**
* @brief Retrieves the scheduling priority of a process. * @brief Retrieves the scheduling priority of a process.
@ -464,7 +464,7 @@ struct utilities {
* @param category A properly initialized handle category. * @param category A properly initialized handle category.
* @return The actual type of the handle as defined by handle_type * @return The actual type of the handle as defined by handle_type
*/ */
static handle_type guess_handle(handle_category category) noexcept; [[nodiscard]] static handle_type guess_handle(handle_category category) noexcept;
/** /**
* @brief Gets the type of the stream to be used with the given descriptor. * @brief Gets the type of the stream to be used with the given descriptor.
@ -484,7 +484,7 @@ struct utilities {
* * `handle_type::UDP` * * `handle_type::UDP`
* * `handle_type::FILE` * * `handle_type::FILE`
*/ */
static handle_type guess_handle(file_handle file) noexcept; [[nodiscard]] static handle_type guess_handle(file_handle file) noexcept;
/** @brief Gets information about the CPUs on the system. /** @brief Gets information about the CPUs on the system.
* *
@ -493,7 +493,7 @@ struct utilities {
* *
* @return A set of descriptors of all the available CPUs. * @return A set of descriptors of all the available CPUs.
*/ */
static std::vector<cpu_info> cpu() noexcept; [[nodiscard]] static std::vector<cpu_info> cpu() noexcept;
/** /**
* @brief Gets a set of descriptors of all the available interfaces. * @brief Gets a set of descriptors of all the available interfaces.
@ -503,7 +503,7 @@ struct utilities {
* *
* @return A set of descriptors of all the available interfaces. * @return A set of descriptors of all the available interfaces.
*/ */
static std::vector<interface_address> interface_addresses() noexcept; [[nodiscard]] static std::vector<interface_address> interface_addresses() noexcept;
/** /**
* @brief IPv6-capable implementation of * @brief IPv6-capable implementation of
@ -518,7 +518,7 @@ struct utilities {
* @param index Network interface index. * @param index Network interface index.
* @return Network interface name. * @return Network interface name.
*/ */
static std::string index_to_name(unsigned int index) noexcept; [[nodiscard]] static std::string index_to_name(unsigned int index) noexcept;
/** /**
* @brief Retrieves a network interface identifier. * @brief Retrieves a network interface identifier.
@ -530,7 +530,7 @@ struct utilities {
* @param index Network interface index. * @param index Network interface index.
* @return Network interface identifier. * @return Network interface identifier.
*/ */
static std::string index_to_iid(unsigned int index) noexcept; [[nodiscard]] static std::string index_to_iid(unsigned int index) noexcept;
/** /**
* @brief Override the use of some standard librarys functions. * @brief Override the use of some standard librarys functions.
@ -561,7 +561,7 @@ struct utilities {
* @brief Gets the load average. * @brief Gets the load average.
* @return `[0,0,0]` on Windows (not available), the load average otherwise. * @return `[0,0,0]` on Windows (not available), the load average otherwise.
*/ */
static std::array<double, 3> load_average() noexcept; [[nodiscard]] static std::array<double, 3> load_average() noexcept;
/** /**
* @brief Store the program arguments. * @brief Store the program arguments.
@ -576,7 +576,7 @@ struct utilities {
* @brief Gets the title of the current process. * @brief Gets the title of the current process.
* @return The process title. * @return The process title.
*/ */
static std::string process_title(); [[nodiscard]] static std::string process_title();
/** /**
* @brief Sets the current process title. * @brief Sets the current process title.
@ -589,7 +589,7 @@ struct utilities {
* @brief Gets memory information (in bytes). * @brief Gets memory information (in bytes).
* @return Memory information. * @return Memory information.
*/ */
static uint64_t total_memory() noexcept; [[nodiscard]] static uint64_t total_memory() noexcept;
/** /**
* @brief Gets the amount of memory available to the process (in bytes). * @brief Gets the amount of memory available to the process (in bytes).
@ -602,32 +602,39 @@ struct utilities {
* *
* @return Amount of memory available to the process. * @return Amount of memory available to the process.
*/ */
static uint64_t constrained_memory() noexcept; [[nodiscard]] static uint64_t constrained_memory() noexcept;
/** /**
* @brief Gets the amount of free memory still available to the process. * @brief Gets the amount of free memory still available to the process.
* @return Amount of free memory still available to the process (in bytes). * @return Amount of free memory still available to the process (in bytes).
*/ */
static uint64_t available_memory() noexcept; [[nodiscard]] static uint64_t available_memory() noexcept;
/**
* @brief Gets the resident set size (RSS) for the current process.
* @return The resident set size (RSS) for the current process or a negative
* value in case of errors.
*/
[[nodiscard]] static int64_t resident_set_memory() noexcept;
/** /**
* @brief Gets the current system uptime. * @brief Gets the current system uptime.
* @return The current system uptime or 0 in case of errors. * @return The current system uptime or 0 in case of errors.
*/ */
static double uptime() noexcept; [[nodiscard]] static double uptime() noexcept;
/** /**
* @brief Gets the resource usage measures for the current process. * @brief Gets the resource usage measures for the current process.
* @return Resource usage measures, zeroes-filled object in case of errors. * @return Resource usage measures, zeroes-filled object in case of errors.
*/ */
static resource_usage rusage() noexcept; [[nodiscard]] static resource_usage rusage() noexcept;
/** /**
* @brief Gets the current system time from a high-resolution clock source. * @brief Gets the current system time from a high-resolution clock source.
* @param source Clock source, either real-time or monotonic. * @param source Clock source, either real-time or monotonic.
* @return Current system time from the given high-resolution clock source. * @return Current system time from the given high-resolution clock source.
*/ */
static timespec64 gettime(clock_id source) noexcept; [[nodiscard]] static timespec64 gettime(clock_id source) noexcept;
/** /**
* @brief Gets the current high-resolution real time. * @brief Gets the current high-resolution real time.
@ -639,7 +646,7 @@ struct utilities {
* *
* @return The current high-resolution real time. * @return The current high-resolution real time.
*/ */
static uint64_t hrtime() noexcept; [[nodiscard]] static uint64_t hrtime() noexcept;
/** /**
* @brief Gets the executable path. * @brief Gets the executable path.
@ -651,7 +658,7 @@ struct utilities {
* @brief Gets the current working directory. * @brief Gets the current working directory.
* @return The current working directory, an empty string in case of errors. * @return The current working directory, an empty string in case of errors.
*/ */
static std::string cwd() noexcept; [[nodiscard]] static std::string cwd() noexcept;
/** /**
* @brief Changes the current working directory. * @brief Changes the current working directory.
@ -665,7 +672,7 @@ struct utilities {
* [`gettimeofday`](https://linux.die.net/man/2/gettimeofday) * [`gettimeofday`](https://linux.die.net/man/2/gettimeofday)
* @return The current time. * @return The current time.
*/ */
static timeval64 time_of_day() noexcept; [[nodiscard]] static timeval64 time_of_day() noexcept;
/** /**
* @brief Causes the calling thread to sleep for a while. * @brief Causes the calling thread to sleep for a while.
@ -678,7 +685,7 @@ struct utilities {
* use (always a non-zero value). * use (always a non-zero value).
* @return Estimate of the amount of parallelism a program should use. * @return Estimate of the amount of parallelism a program should use.
*/ */
static unsigned int available_parallelism() noexcept; [[nodiscard]] static unsigned int available_parallelism() noexcept;
}; };
/** /**
@ -700,7 +707,7 @@ overloaded(Func...) -> overloaded<Func...>;
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "util.cpp" # include "util.ipp"
#endif #endif
#endif // UVW_UTIL_INCLUDE_H #endif // UVW_UTIL_INCLUDE_H

369
src/uvw/util.ipp Normal file
View File

@ -0,0 +1,369 @@
#include "config.h"
namespace uvw {
UVW_INLINE passwd_info::passwd_info(std::shared_ptr<uv_passwd_t> pwd)
: value{std::move(pwd)} {}
UVW_INLINE std::string passwd_info::username() const noexcept {
return ((value && value->username) ? value->username : "");
}
UVW_INLINE decltype(uv_passwd_t::uid) passwd_info::uid() const noexcept {
return (value ? value->uid : decltype(uv_passwd_t::uid){});
}
UVW_INLINE decltype(uv_passwd_t::gid) passwd_info::gid() const noexcept {
return (value ? value->gid : decltype(uv_passwd_t::gid){});
}
UVW_INLINE std::string passwd_info::shell() const noexcept {
return ((value && value->shell) ? value->shell : "");
}
UVW_INLINE std::string passwd_info::homedir() const noexcept {
return ((value && value->homedir) ? value->homedir : "");
}
UVW_INLINE passwd_info::operator bool() const noexcept {
return static_cast<bool>(value);
}
UVW_INLINE uts_name::uts_name(std::shared_ptr<uv_utsname_t> init)
: uname{std::move(init)} {}
UVW_INLINE std::string uts_name::sysname() const noexcept {
return uname ? uname->sysname : "";
}
UVW_INLINE std::string uts_name::release() const noexcept {
return uname ? uname->release : "";
}
UVW_INLINE std::string uts_name::version() const noexcept {
return uname ? uname->version : "";
}
UVW_INLINE std::string uts_name::machine() const noexcept {
return uname ? uname->machine : "";
}
namespace details {
UVW_INLINE void common_alloc_callback(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);
}
UVW_INLINE sockaddr ip_addr(const char *addr, unsigned int port) {
// explicitly cast to avoid `-Wsign-conversion` warnings
// libuv internally just casts to an `unsigned short` anyway
auto signed_port = static_cast<int>(port);
if(sockaddr_in addr_in; uv_ip4_addr(addr, signed_port, &addr_in) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in);
} else if(sockaddr_in6 addr_in6; uv_ip6_addr(addr, signed_port, &addr_in6) == 0) {
return reinterpret_cast<const sockaddr &>(addr_in6);
}
return {};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in &addr) {
if(std::array<char, details::DEFAULT_SIZE> name{}; uv_ip4_name(&addr, name.data(), details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name.data()}, ntohs(addr.sin_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_in6 &addr) {
if(std::array<char, details::DEFAULT_SIZE> name{}; uv_ip6_name(&addr, name.data(), details::DEFAULT_SIZE) == 0) {
return socket_address{std::string{name.data()}, ntohs(addr.sin6_port)};
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr &addr) {
if(addr.sa_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(addr));
} else if(addr.sa_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(addr));
}
return socket_address{};
}
UVW_INLINE socket_address sock_addr(const sockaddr_storage &storage) {
if(storage.ss_family == AF_INET) {
return sock_addr(reinterpret_cast<const sockaddr_in &>(storage));
} else if(storage.ss_family == AF_INET6) {
return sock_addr(reinterpret_cast<const sockaddr_in6 &>(storage));
}
return socket_address{};
}
} // namespace details
UVW_INLINE pid_type utilities::os::pid() noexcept {
return uv_os_getpid();
}
UVW_INLINE pid_type utilities::os::ppid() noexcept {
return uv_os_getppid();
}
UVW_INLINE std::string utilities::os::homedir() noexcept {
return details::try_read(&uv_os_homedir);
}
UVW_INLINE std::string utilities::os::tmpdir() noexcept {
return details::try_read(&uv_os_tmpdir);
}
UVW_INLINE std::string utilities::os::env(const std::string &name) noexcept {
return details::try_read(&uv_os_getenv, name.c_str());
}
UVW_INLINE bool utilities::os::env(const std::string &name, const std::string &value) noexcept {
return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
}
UVW_INLINE std::string utilities::os::hostname() noexcept {
return details::try_read(&uv_os_gethostname);
}
UVW_INLINE uts_name utilities::os::uname() noexcept {
auto ptr = std::make_shared<uv_utsname_t>();
uv_os_uname(ptr.get());
return ptr;
}
UVW_INLINE passwd_info utilities::os::passwd() {
auto deleter = [](uv_passwd_t *passwd) {
uv_os_free_passwd(passwd);
delete passwd;
};
std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
uv_os_get_passwd(ptr.get());
return ptr;
}
UVW_INLINE int utilities::os::priority(pid_type pid) {
int prio = 0;
if(uv_os_getpriority(pid, &prio)) {
prio = UV_PRIORITY_LOW + 1;
}
return prio;
}
UVW_INLINE bool utilities::os::priority(pid_type pid, int prio) {
return 0 == uv_os_setpriority(pid, prio);
}
UVW_INLINE handle_type utilities::guess_handle(handle_category category) noexcept {
switch(category) {
case UV_ASYNC:
return handle_type::ASYNC;
case UV_CHECK:
return handle_type::CHECK;
case UV_FS_EVENT:
return handle_type::FS_EVENT;
case UV_FS_POLL:
return handle_type::FS_POLL;
case UV_HANDLE:
return handle_type::HANDLE;
case UV_IDLE:
return handle_type::IDLE;
case UV_NAMED_PIPE:
return handle_type::PIPE;
case UV_POLL:
return handle_type::POLL;
case UV_PREPARE:
return handle_type::PREPARE;
case UV_PROCESS:
return handle_type::PROCESS;
case UV_STREAM:
return handle_type::STREAM;
case UV_TCP:
return handle_type::TCP;
case UV_TIMER:
return handle_type::TIMER;
case UV_TTY:
return handle_type::TTY;
case UV_UDP:
return handle_type::UDP;
case UV_SIGNAL:
return handle_type::SIGNAL;
case UV_FILE:
return handle_type::FILE;
default:
return handle_type::UNKNOWN;
}
}
UVW_INLINE handle_type utilities::guess_handle(file_handle file) noexcept {
handle_category category = uv_guess_handle(file);
return guess_handle(category);
}
UVW_INLINE std::vector<cpu_info> utilities::cpu() noexcept {
std::vector<cpu_info> cpuinfos;
uv_cpu_info_t *infos;
int count;
if(0 == uv_cpu_info(&infos, &count)) {
for(int next = 0; next < count; ++next) {
cpuinfos.push_back({infos[next].model, infos[next].speed, infos[next].cpu_times});
}
uv_free_cpu_info(infos, count);
}
return cpuinfos;
}
UVW_INLINE std::vector<interface_address> utilities::interface_addresses() noexcept {
std::vector<interface_address> interfaces;
uv_interface_address_t *ifaces{nullptr};
int count{0};
if(0 == uv_interface_addresses(&ifaces, &count)) {
for(int next = 0; next < count; ++next) {
interface_address iface_addr;
iface_addr.name = ifaces[next].name;
std::copy(ifaces[next].phys_addr, (ifaces[next].phys_addr + 6), iface_addr.physical.data());
iface_addr.internal = ifaces[next].is_internal == 0 ? false : true;
if(ifaces[next].address.address4.sin_family == AF_INET) {
iface_addr.address = details::sock_addr(ifaces[next].address.address4);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask4);
} else if(ifaces[next].address.address4.sin_family == AF_INET6) {
iface_addr.address = details::sock_addr(ifaces[next].address.address6);
iface_addr.netmask = details::sock_addr(ifaces[next].netmask.netmask6);
}
interfaces.push_back(std::move(iface_addr));
}
uv_free_interface_addresses(ifaces, count);
}
return interfaces;
}
UVW_INLINE std::string utilities::index_to_name(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoname, index);
}
UVW_INLINE std::string utilities::index_to_iid(unsigned int index) noexcept {
return details::try_read(&uv_if_indextoiid, index);
}
UVW_INLINE bool utilities::replace_allocator(malloc_func_type malloc_func, realloc_func_type realloc_func, calloc_func_type calloc_func, free_func_type free_func) noexcept {
return (0 == uv_replace_allocator(malloc_func, realloc_func, calloc_func, free_func));
}
UVW_INLINE std::array<double, 3> utilities::load_average() noexcept {
std::array<double, 3> avg;
uv_loadavg(avg.data());
return avg;
}
UVW_INLINE char **utilities::setup_args(int argc, char **argv) {
return uv_setup_args(argc, argv);
}
UVW_INLINE std::string utilities::process_title() {
std::array<char, details::DEFAULT_SIZE> buf{};
std::string str{};
if(0 == uv_get_process_title(buf.data(), details::DEFAULT_SIZE)) {
str.assign(buf.data(), details::DEFAULT_SIZE);
}
return str;
}
UVW_INLINE bool utilities::process_title(const std::string &title) {
return (0 == uv_set_process_title(title.c_str()));
}
UVW_INLINE uint64_t utilities::total_memory() noexcept {
return uv_get_total_memory();
}
UVW_INLINE uint64_t utilities::constrained_memory() noexcept {
return uv_get_constrained_memory();
}
UVW_INLINE uint64_t utilities::available_memory() noexcept {
return uv_get_available_memory();
}
UVW_INLINE int64_t utilities::resident_set_memory() noexcept {
size_t res{};
const auto err = uv_resident_set_memory(&res);
return (err == 0) ? static_cast<int64_t>(res) : static_cast<int64_t>(err);
}
UVW_INLINE double utilities::uptime() noexcept {
double ret;
if(0 != uv_uptime(&ret)) {
ret = 0;
}
return ret;
}
UVW_INLINE resource_usage utilities::rusage() noexcept {
resource_usage ru;
auto err = uv_getrusage(&ru);
return err ? resource_usage{} : ru;
}
UVW_INLINE timespec64 utilities::gettime(clock_id source) noexcept {
timespec64 ts;
auto err = uv_clock_gettime(static_cast<uv_clock_id>(source), &ts);
return err ? timespec64{} : ts;
}
UVW_INLINE uint64_t utilities::hrtime() noexcept {
return uv_hrtime();
}
UVW_INLINE std::string utilities::path() noexcept {
return details::try_read(&uv_exepath);
}
UVW_INLINE std::string utilities::cwd() noexcept {
return details::try_read(&uv_cwd);
}
UVW_INLINE bool utilities::chdir(const std::string &dir) noexcept {
return (0 == uv_chdir(dir.data()));
}
UVW_INLINE timeval64 utilities::time_of_day() noexcept {
uv_timeval64_t ret;
uv_gettimeofday(&ret);
return ret;
}
UVW_INLINE void utilities::sleep(unsigned int msec) noexcept {
uv_sleep(msec);
}
UVW_INLINE unsigned int utilities::available_parallelism() noexcept {
return uv_available_parallelism();
}
} // namespace uvw

View File

@ -16,8 +16,8 @@ namespace uvw {
*/ */
template<typename U> template<typename U>
struct uv_type { struct uv_type {
explicit uv_type(loop::token token, std::shared_ptr<loop> ref) noexcept explicit uv_type(loop::token, std::shared_ptr<loop> ref) noexcept
: owner{std::move(ref)}, resource{} {} : owner{std::move(ref)} {}
uv_type(const uv_type &) = delete; uv_type(const uv_type &) = delete;
uv_type(uv_type &&) = delete; uv_type(uv_type &&) = delete;
@ -25,19 +25,11 @@ struct uv_type {
uv_type &operator=(const uv_type &) = delete; uv_type &operator=(const uv_type &) = delete;
uv_type &operator=(uv_type &&) = delete; uv_type &operator=(uv_type &&) = delete;
/**
* @brief Initializes the handle.
* @return Underlying return value.
*/
virtual int init() {
return 0;
}
/** /**
* @brief Gets the loop from which the resource was originated. * @brief Gets the loop from which the resource was originated.
* @return A reference to a loop instance. * @return A reference to a loop instance.
*/ */
loop &parent() const noexcept { [[nodiscard]] loop &parent() const noexcept {
return *owner; return *owner;
} }
@ -56,7 +48,7 @@ struct uv_type {
* *
* @return The underlying raw data structure. * @return The underlying raw data structure.
*/ */
const U *raw() const noexcept { [[nodiscard]] const U *raw() const noexcept {
return &resource; return &resource;
} }
@ -75,13 +67,16 @@ struct uv_type {
* *
* @return The underlying raw data structure. * @return The underlying raw data structure.
*/ */
U *raw() noexcept { [[nodiscard]] U *raw() noexcept {
return &resource; return &resource;
} }
protected:
~uv_type() = default;
private: private:
std::shared_ptr<loop> owner; std::shared_ptr<loop> owner;
U resource; U resource{};
}; };
} // namespace uvw } // namespace uvw

View File

@ -1,30 +1,2 @@
#ifdef UVW_AS_LIB #include "work.h"
# include "work.h" #include "work.ipp"
#endif
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE work_req::work_req(loop::token token, std::shared_ptr<loop> ref, task t)
: request{token, std::move(ref)}, func{t} {}
UVW_INLINE void work_req::work_callback(uv_work_t *req) {
static_cast<work_req *>(req->data)->func();
}
UVW_INLINE void work_req::after_work_callback(uv_work_t* req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(work_event{});
}
}
UVW_INLINE int work_req::queue() {
return this->leak_if(uv_queue_work(parent().raw(), raw(), &work_callback, &after_work_callback));
}
} // namespace uvw

View File

@ -20,7 +20,7 @@ struct work_event {};
* *
* To create a `work_req` through a `loop`, arguments follow: * To create a `work_req` through a `loop`, arguments follow:
* *
* * A valid instance of a `Task`, that is of type `std::function<void(void)>`. * * A valid instance of a `Task`, that is of type `std::function<void()>`.
* *
* See the official * See the official
* [documentation](http://docs.libuv.org/en/v1.x/threadpool.html) * [documentation](http://docs.libuv.org/en/v1.x/threadpool.html)
@ -31,7 +31,7 @@ class work_req final: public request<work_req, uv_work_t, work_event> {
static void after_work_callback(uv_work_t *req, int status); static void after_work_callback(uv_work_t *req, int status);
public: public:
using task = std::function<void(void)>; using task = std::function<void()>;
explicit work_req(loop::token token, std::shared_ptr<loop> ref, task t); explicit work_req(loop::token token, std::shared_ptr<loop> ref, task t);
@ -53,7 +53,7 @@ private:
} // namespace uvw } // namespace uvw
#ifndef UVW_AS_LIB #ifndef UVW_AS_LIB
# include "work.cpp" # include "work.ipp"
#endif #endif
#endif // UVW_WORK_INCLUDE_H #endif // UVW_WORK_INCLUDE_H

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

@ -0,0 +1,25 @@
#include <utility>
#include "config.h"
namespace uvw {
UVW_INLINE work_req::work_req(loop::token token, std::shared_ptr<loop> ref, task t)
: request{token, std::move(ref)}, func{std::move(t)} {}
UVW_INLINE void work_req::work_callback(uv_work_t *req) {
static_cast<work_req *>(req->data)->func();
}
UVW_INLINE void work_req::after_work_callback(uv_work_t *req, int status) {
if(auto ptr = reserve(req); status) {
ptr->publish(error_event{status});
} else {
ptr->publish(work_event{});
}
}
UVW_INLINE int work_req::queue() {
return this->leak_if(uv_queue_work(parent().raw(), raw(), &work_callback, &after_work_callback));
}
} // namespace uvw

3
subprojects/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore
!*.wrap

13
subprojects/libuv.wrap Normal file
View File

@ -0,0 +1,13 @@
[wrap-file]
directory = libuv-v1.48.0
source_url = https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
source_filename = libuv-v1.48.0.tar.gz
source_hash = 7f1db8ac368d89d1baf163bac1ea5fe5120697a73910c8ae6b2fffb3551d59fb
patch_filename = libuv_1.48.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/libuv_1.48.0-1/get_patch
patch_hash = 27b18917c914a5d6dfb459073710e9bfb6b2962d69d4e0bad5bc7b1173482be7
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libuv_1.48.0-1/libuv-v1.48.0.tar.gz
wrapdb_version = 1.48.0-1
[provide]
libuv = libuv_dep

View File

@ -7,7 +7,7 @@ include(FetchContent)
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
if(FIND_GTEST_PACKAGE) if(UVW_FIND_GTEST_PACKAGE)
find_package(GTest REQUIRED) find_package(GTest REQUIRED)
else() else()
FetchContent_Declare( FetchContent_Declare(
@ -19,18 +19,22 @@ else()
FetchContent_GetProperties(googletest) FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_Populate(googletest) FetchContent_MakeAvailable(googletest)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
add_library(GTest::Main ALIAS gtest_main) add_library(GTest::Main ALIAS gtest_main)
target_compile_features(gtest PUBLIC cxx_std_17) target_compile_features(gtest PUBLIC cxx_std_17)
set_target_properties(gtest PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gtest_main PUBLIC cxx_std_17) target_compile_features(gtest_main PUBLIC cxx_std_17)
set_target_properties(gtest_main PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gmock PUBLIC cxx_std_17) target_compile_features(gmock PUBLIC cxx_std_17)
set_target_properties(gmock PROPERTIES CXX_CLANG_TIDY "")
target_compile_features(gmock_main PUBLIC cxx_std_17) target_compile_features(gmock_main PUBLIC cxx_std_17)
set_target_properties(gmock_main PROPERTIES CXX_CLANG_TIDY "")
if(CMAKE_SYSTEM_NAME MATCHES OpenBSD) if(CMAKE_SYSTEM_NAME MATCHES OpenBSD)
target_compile_options(gtest PRIVATE -Wno-error) target_compile_options(gtest PRIVATE -Wno-error)
@ -41,7 +45,7 @@ if(WIN32)
set(WINSOCK2 ws2_32) set(WINSOCK2 ws2_32)
endif() endif()
function(ADD_UVW_TEST TEST_NAME TEST_SOURCE) function(UVW_ADD_TEST TEST_NAME TEST_SOURCE)
add_executable(${TEST_NAME} ${TEST_SOURCE}) add_executable(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries( target_link_libraries(
@ -69,16 +73,16 @@ function(ADD_UVW_TEST TEST_NAME TEST_SOURCE)
add_test(NAME uvw_${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}>) add_test(NAME uvw_${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}>)
endfunction() endfunction()
function(ADD_UVW_DIR_TEST TEST_NAME TEST_SOURCE) function(UVW_ADD_DIR_TEST TEST_NAME TEST_SOURCE)
ADD_UVW_TEST(${TEST_NAME} ${TEST_SOURCE}) UVW_ADD_TEST(${TEST_NAME} ${TEST_SOURCE})
string(TOUPPER "${TEST_NAME}" TEST_NAME_UPPER) string(TOUPPER "${TEST_NAME}" TEST_NAME_UPPER)
set(TEST_DIR_VAR "TARGET_${TEST_NAME_UPPER}_DIR") set(TEST_DIR_VAR "TARGET_${TEST_NAME_UPPER}_DIR")
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}_data) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}_data)
target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_DIR_VAR}="${TEST_NAME}_data") target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_DIR_VAR}="${TEST_NAME}_data")
endfunction() endfunction()
function(ADD_UVW_LIB_TEST TEST_NAME TEST_SOURCE) function(UVW_ADD_LIB_TEST TEST_NAME TEST_SOURCE)
ADD_UVW_TEST(${TEST_NAME} ${TEST_SOURCE}) UVW_ADD_TEST(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(${TEST_NAME} PRIVATE ${CMAKE_DL_LIBS}) target_link_libraries(${TEST_NAME} PRIVATE ${CMAKE_DL_LIBS})
target_compile_definitions(${TEST_NAME} PRIVATE TARGET_LIB_SO="$<TARGET_FILE:fake>") target_compile_definitions(${TEST_NAME} PRIVATE TARGET_LIB_SO="$<TARGET_FILE:fake>")
endfunction() endfunction()
@ -87,39 +91,39 @@ add_library(fake SHARED fake.cpp)
# List of available targets # List of available targets
option(BUILD_DNS_TEST "Build DNS test." OFF) option(UVW_BUILD_DNS_TEST "Build DNS test." OFF)
ADD_UVW_TEST(main main.cpp) UVW_ADD_TEST(main main.cpp)
ADD_UVW_TEST(async uvw/async.cpp) UVW_ADD_TEST(async uvw/async.cpp)
ADD_UVW_TEST(check uvw/check.cpp) UVW_ADD_TEST(check uvw/check.cpp)
ADD_UVW_TEST(emitter uvw/emitter.cpp) UVW_ADD_TEST(emitter uvw/emitter.cpp)
ADD_UVW_DIR_TEST(file_req uvw/file_req.cpp) UVW_ADD_DIR_TEST(file_req uvw/file_req.cpp)
ADD_UVW_DIR_TEST(fs_event uvw/fs_event.cpp) UVW_ADD_DIR_TEST(fs_event uvw/fs_event.cpp)
ADD_UVW_DIR_TEST(fs_req uvw/fs_req.cpp) UVW_ADD_DIR_TEST(fs_req uvw/fs_req.cpp)
ADD_UVW_TEST(handle uvw/handle.cpp) UVW_ADD_TEST(handle uvw/handle.cpp)
ADD_UVW_TEST(idle uvw/idle.cpp) UVW_ADD_TEST(idle uvw/idle.cpp)
ADD_UVW_LIB_TEST(lib uvw/lib.cpp) UVW_ADD_LIB_TEST(lib uvw/lib.cpp)
ADD_UVW_TEST(loop uvw/loop.cpp) UVW_ADD_TEST(loop uvw/loop.cpp)
ADD_UVW_DIR_TEST(pipe uvw/pipe.cpp) UVW_ADD_DIR_TEST(pipe uvw/pipe.cpp)
ADD_UVW_TEST(prepare uvw/prepare.cpp) UVW_ADD_TEST(prepare uvw/prepare.cpp)
ADD_UVW_TEST(process uvw/process.cpp) UVW_ADD_TEST(process uvw/process.cpp)
ADD_UVW_TEST(request uvw/request.cpp) UVW_ADD_TEST(request uvw/request.cpp)
ADD_UVW_TEST(resource uvw/resource.cpp) UVW_ADD_TEST(resource uvw/resource.cpp)
ADD_UVW_TEST(signal uvw/signal.cpp) UVW_ADD_TEST(signal uvw/signal.cpp)
ADD_UVW_TEST(stream uvw/stream.cpp) UVW_ADD_TEST(stream uvw/stream.cpp)
ADD_UVW_TEST(tcp uvw/tcp.cpp) UVW_ADD_TEST(tcp uvw/tcp.cpp)
ADD_UVW_TEST(thread uvw/thread.cpp) UVW_ADD_TEST(thread uvw/thread.cpp)
ADD_UVW_TEST(timer uvw/timer.cpp) UVW_ADD_TEST(timer uvw/timer.cpp)
ADD_UVW_TEST(tty uvw/tty.cpp) UVW_ADD_TEST(tty uvw/tty.cpp)
ADD_UVW_TEST(udp uvw/udp.cpp) UVW_ADD_TEST(udp uvw/udp.cpp)
ADD_UVW_TEST(uv_type uvw/uv_type.cpp) UVW_ADD_TEST(uv_type uvw/uv_type.cpp)
ADD_UVW_TEST(util uvw/util.cpp) UVW_ADD_TEST(util uvw/util.cpp)
ADD_UVW_TEST(work uvw/work.cpp) UVW_ADD_TEST(work uvw/work.cpp)
if(NOT CMAKE_SYSTEM_NAME MATCHES OpenBSD) if(NOT CMAKE_SYSTEM_NAME MATCHES OpenBSD)
ADD_UVW_DIR_TEST(file_req_sendfile uvw/file_req_sendfile.cpp) UVW_ADD_DIR_TEST(file_req_sendfile uvw/file_req_sendfile.cpp)
endif() endif()
if(BUILD_DNS_TEST) if(UVW_BUILD_DNS_TEST)
ADD_UVW_TEST(dns uvw/dns.cpp) UVW_ADD_TEST(dns uvw/dns.cpp)
endif() endif()

View File

@ -1,5 +1,3 @@
#include <stdio.h>
extern "C" int fake_func(double *); extern "C" int fake_func(double *);
int fake_func(double *d) { int fake_func(double *d) {

View File

@ -1,7 +1,7 @@
#include <cassert> #include <cassert>
#include <chrono>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <utility>
#include <uvw.hpp> #include <uvw.hpp>
void listen(uvw::loop &loop) { void listen(uvw::loop &loop) {
@ -28,7 +28,7 @@ void listen(uvw::loop &loop) {
std::cout << "remote: " << remote.ip << " " << remote.port << std::endl; std::cout << "remote: " << remote.ip << " " << remote.port << std::endl;
client->on<uvw::data_event>([](const uvw::data_event &event, uvw::tcp_handle &) { client->on<uvw::data_event>([](const uvw::data_event &event, uvw::tcp_handle &) {
std::cout.write(event.data.get(), event.length) << std::endl; std::cout.write(event.data.get(), static_cast<std::streamsize>(event.length)) << std::endl;
std::cout << "data length: " << event.length << std::endl; std::cout << "data length: " << event.length << std::endl;
}); });
@ -65,7 +65,7 @@ void conn(uvw::loop &loop) {
auto dataTryWrite = std::unique_ptr<char[]>(new char[1]{'a'}); auto dataTryWrite = std::unique_ptr<char[]>(new char[1]{'a'});
int bw = handle.try_write(std::move(dataTryWrite), 1); int bw = handle.try_write(std::move(dataTryWrite), 1);
std::cout << "written: " << ((int)bw) << std::endl; std::cout << "written: " << static_cast<int>(bw) << std::endl;
auto dataWrite = std::unique_ptr<char[]>(new char[2]{'b', 'c'}); auto dataWrite = std::unique_ptr<char[]>(new char[2]{'b', 'c'});
handle.write(std::move(dataWrite), 2); handle.write(std::move(dataWrite), 2);

View File

@ -1,4 +1,3 @@
#include <chrono>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <uvw/fs.h> #include <uvw/fs.h>

View File

@ -107,7 +107,7 @@ TEST(FsReq, Stat) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::STAT) { if(event.type == uvw::fs_req::fs_type::STAT) {
ASSERT_FALSE(checkFsStatEvent); ASSERT_FALSE(checkFsStatEvent);
checkFsStatEvent = true; checkFsStatEvent = true;
@ -160,7 +160,7 @@ TEST(FsReq, Lstat) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::LSTAT) { if(event.type == uvw::fs_req::fs_type::LSTAT) {
ASSERT_FALSE(checkFsLstatEvent); ASSERT_FALSE(checkFsLstatEvent);
checkFsLstatEvent = true; checkFsLstatEvent = true;
@ -214,7 +214,7 @@ TEST(FsReq, Rename) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::RENAME) { if(event.type == uvw::fs_req::fs_type::RENAME) {
ASSERT_FALSE(checkFsRenameEvent); ASSERT_FALSE(checkFsRenameEvent);
checkFsRenameEvent = true; checkFsRenameEvent = true;
@ -265,7 +265,7 @@ TEST(FsReq, Access) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::ACCESS) { if(event.type == uvw::fs_req::fs_type::ACCESS) {
ASSERT_FALSE(checkFsAccessEvent); ASSERT_FALSE(checkFsAccessEvent);
checkFsAccessEvent = true; checkFsAccessEvent = true;
@ -315,7 +315,7 @@ TEST(FsReq, Chmod) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::CHMOD) { if(event.type == uvw::fs_req::fs_type::CHMOD) {
ASSERT_FALSE(checkFsChmodEvent); ASSERT_FALSE(checkFsChmodEvent);
checkFsChmodEvent = true; checkFsChmodEvent = true;
@ -365,7 +365,7 @@ TEST(FsReq, Utime) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::UTIME) { if(event.type == uvw::fs_req::fs_type::UTIME) {
ASSERT_FALSE(checkFsUtimeEvent); ASSERT_FALSE(checkFsUtimeEvent);
checkFsUtimeEvent = true; checkFsUtimeEvent = true;
@ -600,7 +600,7 @@ TEST(FsReq, Realpath) {
fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fsReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); }); fileReq->on<uvw::error_event>([](const auto &, auto &) { FAIL(); });
fsReq->on<uvw::fs_event>([&](const auto &event, auto &req) { fsReq->on<uvw::fs_event>([&](const auto &event, auto &) {
if(event.type == uvw::fs_req::fs_type::REALPATH) { if(event.type == uvw::fs_req::fs_type::REALPATH) {
ASSERT_FALSE(checkFsRealpathEvent); ASSERT_FALSE(checkFsRealpathEvent);
ASSERT_NE(event.path, nullptr); ASSERT_NE(event.path, nullptr);

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