From eb39dde61ad99be7be2fac99ecf5761c4aeb54e6 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Thu, 5 Jun 2025 20:30:00 +0300 Subject: [PATCH 01/10] No clang-tidy action on save --- .vscode/settings.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 29e6e34..31c655f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,13 +3,12 @@ "-Dcpp_channel_build_examples=ON", "-Dcpp_channel_build_tests=ON" ], - "editor.codeActionsOnSave": { - "source.fixAll": "explicit" - }, + "clang-tidy.fixOnSave": false, + "clang-tidy.lintOnSave": false, "editor.formatOnSave": true, "clang-format.executable": "clang-format", "clang-format.style": "file", "editor.defaultFormatter": "xaver.clang-format", "files.insertFinalNewline": true, - "files.trimFinalNewlines": true, + "files.trimFinalNewlines": true } From 8334668710014b07ce77a7b0c067a6750dc02ef5 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Thu, 5 Jun 2025 20:40:21 +0300 Subject: [PATCH 02/10] Set copyright --- include/msd/blocking_iterator.hpp | 2 +- include/msd/channel.hpp | 2 +- include/msd/channel.inl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/msd/blocking_iterator.hpp b/include/msd/blocking_iterator.hpp index 251f189..c7510c2 100644 --- a/include/msd/blocking_iterator.hpp +++ b/include/msd/blocking_iterator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Andrei Avram +// Copyright (C) 2020-2025 Andrei Avram #ifndef MSD_CHANNEL_BLOCKING_ITERATOR_HPP_ #define MSD_CHANNEL_BLOCKING_ITERATOR_HPP_ diff --git a/include/msd/channel.hpp b/include/msd/channel.hpp index 322d265..a1a239a 100644 --- a/include/msd/channel.hpp +++ b/include/msd/channel.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Andrei Avram +// Copyright (C) 2020-2025 Andrei Avram #ifndef MSD_CHANNEL_HPP_ #define MSD_CHANNEL_HPP_ diff --git a/include/msd/channel.inl b/include/msd/channel.inl index fbf0f5d..e560b4e 100644 --- a/include/msd/channel.inl +++ b/include/msd/channel.inl @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Andrei Avram +// Copyright (C) 2020-2025 Andrei Avram namespace msd { From 07beb33b4124b18d14fbd87dfc426154aae8ee19 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Thu, 5 Jun 2025 20:45:11 +0300 Subject: [PATCH 03/10] Lock before checking if closed --- include/msd/channel.inl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/msd/channel.inl b/include/msd/channel.inl index e560b4e..2ce97e3 100644 --- a/include/msd/channel.inl +++ b/include/msd/channel.inl @@ -10,14 +10,14 @@ constexpr channel::channel(const size_type capacity) : cap_{capacity} template channel::type>& operator<<(channel::type>& ch, T&& in) { - if (ch.closed()) { - throw closed_channel{"cannot write on closed channel"}; - } - { std::unique_lock lock{ch.mtx_}; ch.waitBeforeWrite(lock); + if (ch.closed()) { + throw closed_channel{"cannot write on closed channel"}; + } + ch.queue_.push(std::forward(in)); ++ch.size_; } @@ -30,14 +30,14 @@ channel::type>& operator<<(channel template channel& operator>>(channel& ch, T& out) { - if (ch.closed() && ch.empty()) { - return ch; - } - { std::unique_lock lock{ch.mtx_}; ch.waitBeforeRead(lock); + if (ch.closed() && ch.empty()) { + return ch; + } + if (!ch.empty()) { out = std::move(ch.queue_.front()); ch.queue_.pop(); From 94fbce7c631d9ca288d2fb118fb67c0f48f74a99 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:39:00 +0300 Subject: [PATCH 04/10] Remove unused header --- include/msd/channel.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/msd/channel.hpp b/include/msd/channel.hpp index a1a239a..d94c372 100644 --- a/include/msd/channel.hpp +++ b/include/msd/channel.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "blocking_iterator.hpp" From f2ecf9971f1bd40525af8af50ed7adefad6a7324 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:39:23 +0300 Subject: [PATCH 05/10] Remove redundant inline --- include/msd/channel.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/msd/channel.hpp b/include/msd/channel.hpp index d94c372..7306ef3 100644 --- a/include/msd/channel.hpp +++ b/include/msd/channel.hpp @@ -74,12 +74,12 @@ class channel { /** * Returns the number of elements in the channel. */ - NODISCARD inline size_type constexpr size() const noexcept; + NODISCARD size_type constexpr size() const noexcept; /** * Returns true if there are no elements in channel. */ - NODISCARD inline bool constexpr empty() const noexcept; + NODISCARD bool constexpr empty() const noexcept; /** * Closes the channel. From ee2c08dbe2487fb1868b4fdf78da942ed11fa639 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:39:51 +0300 Subject: [PATCH 06/10] Exlcude clang tidy rules --- .clang-tidy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.clang-tidy b/.clang-tidy index a50f424..2445dea 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,6 +9,8 @@ Checks: > -hicpp-named-parameter, -readability-named-parameter, -altera-unroll-loops, + -llvmlibc-inline-function-decl, + -cppcoreguidelines-avoid-const-or-ref-data-members WarningsAsErrors: "*" From ba4627ea9fc6da6daa5c47822c36e034a1cf516f Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:43:46 +0300 Subject: [PATCH 07/10] Split CI jobs --- .github/workflows/cmake.yml | 68 ++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b96e5a7..ad086e9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,17 +1,26 @@ -# https://gist.github.com/NickNaso/0d478f1481686d5bcc868cac06620a60 name: build on: push: branches: - master + paths-ignore: + - '.vscode/**' + - 'LICENSE' + - 'README.md' pull_request: + paths-ignore: + - '.vscode/**' + - 'LICENSE' + - 'README.md' workflow_dispatch: - schedule: - - cron: '0 18 1 * *' + +env: + CTEST_OUTPUT_ON_FAILURE: ON + CTEST_PARALLEL_LEVEL: 2 jobs: - build: + test: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} @@ -23,65 +32,68 @@ jobs: name: "Ubuntu Latest GCC (Release)", os: ubuntu-latest, build_type: "Release", - coverage: false, } - { name: "Ubuntu 22.04 GCC (Debug)", os: ubuntu-22.04, build_type: "Debug", - coverage: true, } - { name: "macOS Latest Clang (Release)", os: macos-latest, build_type: "Release", - coverage: false, } - { name: "Windows Latest (Release)", os: windows-latest, build_type: "Release", - coverage: false, } steps: - uses: actions/checkout@v4 - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands run: cmake -E make_directory ${{github.workspace}}/build - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash working-directory: ${{github.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -Dcpp_channel_build_examples=ON -Dcpp_channel_build_tests=ON + run: cmake ${{ github.workspace }} -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -Dcpp_channel_build_examples=ON -Dcpp_channel_build_tests=ON - name: Build working-directory: ${{github.workspace}}/build - shell: bash - # Execute the build. You can specify a specific target with "--target " run: cmake --build . --config ${{ matrix.config.build_type }} --target tests - name: Test working-directory: ${{github.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{ matrix.config.build_type }} --verbose -R channel_test* + - name: Run examples + working-directory: ${{github.workspace}}/build + run: cmake --build . --config ${{ matrix.config.build_type }} --target examples + + coverage: + name: Coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Create Build Environment + run: cmake -E make_directory ${{github.workspace}}/build + + - name: Configure CMake + working-directory: ${{github.workspace}}/build + run: cmake ${{ github.workspace }} -DCMAKE_BUILD_TYPE=Debug -Dcpp_channel_build_tests=ON + + - name: Build + working-directory: ${{github.workspace}}/build + run: cmake --build . --config Debug --target tests + + - name: Test + working-directory: ${{github.workspace}}/build + run: ctest -C Debug --verbose -R channel_test11 + - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} - if: matrix.config.coverage == true - - - name: Run examples - working-directory: ${{github.workspace}}/build - shell: bash - run: cmake --build . --config ${{ matrix.config.build_type }} --target examples From 258c5d26a18f35e226020057d44bb760626c45f8 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 17:33:01 +0300 Subject: [PATCH 08/10] Format files --- .github/workflows/cmake.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ad086e9..6808ee2 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -97,3 +97,13 @@ jobs: uses: codecov/codecov-action@v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} + + clang-format: + name: Clang Format + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Run Clang Format + run: clang-format --dry-run --Werror $(find include -type f) From 7f223894cc30ce023877ecf23c75ed56c3098080 Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:08:05 +0300 Subject: [PATCH 09/10] Move implementation from inl to hpp --- include/msd/channel.hpp | 80 +++++++++++++++++++++++++----- include/msd/channel.inl | 107 ---------------------------------------- 2 files changed, 69 insertions(+), 118 deletions(-) delete mode 100644 include/msd/channel.inl diff --git a/include/msd/channel.hpp b/include/msd/channel.hpp index 7306ef3..814e4c1 100644 --- a/include/msd/channel.hpp +++ b/include/msd/channel.hpp @@ -53,7 +53,7 @@ class channel { * * @param capacity Number of elements the channel can store before blocking. */ - explicit constexpr channel(size_type capacity); + explicit constexpr channel(const size_type capacity) : cap_{capacity} {} /** * Pushes an element into the channel. @@ -74,28 +74,35 @@ class channel { /** * Returns the number of elements in the channel. */ - NODISCARD size_type constexpr size() const noexcept; + NODISCARD size_type constexpr size() const noexcept { return size_; } /** * Returns true if there are no elements in channel. */ - NODISCARD bool constexpr empty() const noexcept; + NODISCARD bool constexpr empty() const noexcept { return size_ == 0; } /** * Closes the channel. */ - inline void close() noexcept; + inline void close() noexcept + { + { + std::unique_lock lock{mtx_}; + is_closed_.store(true); + } + cnd_.notify_all(); + } /** * Returns true if the channel is closed. */ - NODISCARD inline bool closed() const noexcept; + NODISCARD inline bool closed() const noexcept { return is_closed_.load(); } /** * Iterator */ - iterator begin() noexcept; - iterator end() noexcept; + iterator begin() noexcept { return blocking_iterator>{*this}; } + iterator end() noexcept { return blocking_iterator>{*this}; } /** * Channel cannot be copied or moved. @@ -114,13 +121,64 @@ class channel { std::condition_variable cnd_; std::atomic is_closed_{false}; - inline void waitBeforeRead(std::unique_lock&); - inline void waitBeforeWrite(std::unique_lock&); + inline void waitBeforeRead(std::unique_lock& lock) + { + cnd_.wait(lock, [this]() { return !empty() || closed(); }); + }; + + inline void waitBeforeWrite(std::unique_lock& lock) + { + if (cap_ > 0 && size_ == cap_) { + cnd_.wait(lock, [this]() { return size_ < cap_; }); + } + } + friend class blocking_iterator; }; -} // namespace msd +template +channel::type>& operator<<(channel::type>& ch, T&& in) +{ + { + std::unique_lock lock{ch.mtx_}; + ch.waitBeforeWrite(lock); + + if (ch.closed()) { + throw closed_channel{"cannot write on closed channel"}; + } + + ch.queue_.push(std::forward(in)); + ++ch.size_; + } + + ch.cnd_.notify_one(); + + return ch; +} -#include "channel.inl" +template +channel& operator>>(channel& ch, T& out) +{ + { + std::unique_lock lock{ch.mtx_}; + ch.waitBeforeRead(lock); + + if (ch.closed() && ch.empty()) { + return ch; + } + + if (!ch.empty()) { + out = std::move(ch.queue_.front()); + ch.queue_.pop(); + --ch.size_; + } + } + + ch.cnd_.notify_one(); + + return ch; +} + +} // namespace msd #endif // MSD_CHANNEL_HPP_ diff --git a/include/msd/channel.inl b/include/msd/channel.inl deleted file mode 100644 index 2ce97e3..0000000 --- a/include/msd/channel.inl +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2020-2025 Andrei Avram - -namespace msd { - -template -constexpr channel::channel(const size_type capacity) : cap_{capacity} -{ -} - -template -channel::type>& operator<<(channel::type>& ch, T&& in) -{ - { - std::unique_lock lock{ch.mtx_}; - ch.waitBeforeWrite(lock); - - if (ch.closed()) { - throw closed_channel{"cannot write on closed channel"}; - } - - ch.queue_.push(std::forward(in)); - ++ch.size_; - } - - ch.cnd_.notify_one(); - - return ch; -} - -template -channel& operator>>(channel& ch, T& out) -{ - { - std::unique_lock lock{ch.mtx_}; - ch.waitBeforeRead(lock); - - if (ch.closed() && ch.empty()) { - return ch; - } - - if (!ch.empty()) { - out = std::move(ch.queue_.front()); - ch.queue_.pop(); - --ch.size_; - } - } - - ch.cnd_.notify_one(); - - return ch; -} - -template -constexpr typename channel::size_type channel::size() const noexcept -{ - return size_; -} - -template -constexpr bool channel::empty() const noexcept -{ - return size_ == 0; -} - -template -void channel::close() noexcept -{ - { - std::unique_lock lock{mtx_}; - is_closed_.store(true); - } - cnd_.notify_all(); -} - -template -bool channel::closed() const noexcept -{ - return is_closed_.load(); -} - -template -blocking_iterator> channel::begin() noexcept -{ - return blocking_iterator>{*this}; -} - -template -blocking_iterator> channel::end() noexcept -{ - return blocking_iterator>{*this}; -} - -template -void channel::waitBeforeRead(std::unique_lock& lock) -{ - cnd_.wait(lock, [this]() { return !empty() || closed(); }); -} - -template -void channel::waitBeforeWrite(std::unique_lock& lock) -{ - if (cap_ > 0 && size_ == cap_) { - cnd_.wait(lock, [this]() { return size_ < cap_; }); - } -} - -} // namespace msd From 3791d772cd08adcc2153de57cfef7de1416cf38d Mon Sep 17 00:00:00 2001 From: Andrei Avram <6795248+andreiavrammsd@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:13:12 +0300 Subject: [PATCH 10/10] Set coverage threshold --- codecov.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/codecov.yml b/codecov.yml index 7332f27..83e8aae 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,11 +1,14 @@ coverage: - precision: 2 - round: down - range: "100...100" status: - project: true - patch: true - changes: true - + patch: + default: + target: 96% + threshold: 0% + if_ci_failed: error + project: + default: + target: 97% + threshold: 0% + if_ci_failed: error ignore: - 'tests/*'