From 4f606cff412ed5c1590dee7aa6e5412d632f11fa Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sat, 4 Oct 2025 20:23:07 +0800 Subject: [PATCH 01/81] ci: Remove temporary workflow file --- .../workflows/deploy-docs-existing-tags.yml | 116 ------------------ 1 file changed, 116 deletions(-) delete mode 100644 .github/workflows/deploy-docs-existing-tags.yml diff --git a/.github/workflows/deploy-docs-existing-tags.yml b/.github/workflows/deploy-docs-existing-tags.yml deleted file mode 100644 index 2f942f5..0000000 --- a/.github/workflows/deploy-docs-existing-tags.yml +++ /dev/null @@ -1,116 +0,0 @@ -# .github/workflows/deploy-docs-existing-tags.yml -name: Deploy Documentation - Existing Tags - -on: - push: - branches: - - test # 监听 test 分支 push - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y doxygen graphviz plantuml jq - - - name: Set tags to deploy - id: tags - run: | - # 一次性部署的指定 tags - TAGS="v0.1.0 v0.1.2 v0.1.4" - echo "tags=$TAGS" >> $GITHUB_OUTPUT - echo "Deploying tags: $TAGS" - - - name: Build and deploy documentation - env: - GH_PAT: ${{ secrets.GH_PAT }} - TAGS: ${{ steps.tags.outputs.tags }} - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - # 克隆文档仓库 - git clone -b master https://$GH_PAT@github.com/FrozenLemonTee/original_docs.git deploy-repo - - for TAG in $TAGS; do - echo "Processing tag: $TAG" - - # 检出 tag - git checkout $TAG || { echo "Tag $TAG not found"; continue; } - - # 提取版本号 - VERSION=${TAG#v} - - # 清理并创建文档目录 - mkdir -p ../original_docs/docs/html - doxygen Doxyfile > doxygen.log 2>&1 - - # 检查 HTML 是否生成 - if [ ! -d "../original_docs/docs/html" ]; then - echo "Warning: Documentation not generated for $TAG" - continue - fi - - # 创建版本信息文件 - echo '' > ../original_docs/docs/html/version.html - echo 'Version Info' >> ../original_docs/docs/html/version.html - echo "

Documentation Version

" >> ../original_docs/docs/html/version.html - echo "

Version: $VERSION

" >> ../original_docs/docs/html/version.html - echo "

Tag: $TAG

" >> ../original_docs/docs/html/version.html - echo "

Build Date: $(date -u)

" >> ../original_docs/docs/html/version.html - echo "

Commit: $(git rev-parse $TAG)

" >> ../original_docs/docs/html/version.html - echo '' >> ../original_docs/docs/html/version.html - - # 部署到文档仓库 - cd deploy-repo - mkdir -p versions - VERSION_DIR="versions/$VERSION" - rm -rf "$VERSION_DIR" - mkdir -p "$VERSION_DIR" - cp -r ../../original_docs/docs/html/* "$VERSION_DIR"/ - cd .. - done - - # 更新主 index.html 和 versions/index.html - cd deploy-repo - - echo '' > index.html - echo '' >> index.html - echo '

Redirecting to stable documentation...

' >> index.html - echo '

Available versions:

Recent tag versions:

' >> index.html - - # versions/index.html - echo '' > versions/index.html - echo 'Versioned Documentation' >> versions/index.html - echo '

Versioned Documentation

Select a version:

Stable (master branch)

' >> versions/index.html - echo '

Latest (test branch)

' >> versions/index.html - - # 提交推送 - git add . - if git diff-index --quiet HEAD --; then - echo "No changes to deploy" - else - git commit -m "Deploy documentation for tags $TAGS" - git push origin master - echo "✅ Documentation deployed successfully for tags $TAGS" - fi From e5d2675515bab71b1903ddcd4fffb561bb874fcb Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sat, 4 Oct 2025 20:23:32 +0800 Subject: [PATCH 02/81] ci: Change branch to normal --- .github/workflows/deploy-docs-latest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs-latest.yml b/.github/workflows/deploy-docs-latest.yml index a25ed8a..fbf347a 100644 --- a/.github/workflows/deploy-docs-latest.yml +++ b/.github/workflows/deploy-docs-latest.yml @@ -4,7 +4,7 @@ name: Deploy Documentation - Latest on: push: - branches: [ master ] # Temporary change from test to master to avoid concurrency push + branches: [ test ] jobs: build-and-deploy: From 0028a921ea420f0c7ef90599ed6e25fab1438db2 Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sat, 4 Oct 2025 20:38:08 +0800 Subject: [PATCH 03/81] ci: Set default build type to release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bcdefab..0c8993b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(ORIGINAL_VERSION 0.1.5) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED True) if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type (default Debug)" FORCE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (default Release)" FORCE) endif() include(CMakePackageConfigHelpers) From 6e85f2b31ff90abb8ea71684089455c7a025d9c8 Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sat, 4 Oct 2025 21:41:40 +0800 Subject: [PATCH 04/81] ci: Fix doc update logic --- .github/workflows/deploy-docs-stable.yml | 41 +++++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-docs-stable.yml b/.github/workflows/deploy-docs-stable.yml index 0b41a78..7c8471f 100644 --- a/.github/workflows/deploy-docs-stable.yml +++ b/.github/workflows/deploy-docs-stable.yml @@ -45,7 +45,7 @@ jobs: echo '' >> ../original_docs/docs/html/version.html echo '

Documentation Version

' >> ../original_docs/docs/html/version.html echo '

Version: stable

' >> ../original_docs/docs/html/version.html - echo '

Branch: master

' >> index.html + echo '

Branch: master

' >> ../original_docs/docs/html/version.html echo "

Build Date: $(date -u)

" >> ../original_docs/docs/html/version.html echo "

Commit: ${{ github.sha }}

" >> ../original_docs/docs/html/version.html echo '' >> ../original_docs/docs/html/version.html @@ -64,12 +64,12 @@ jobs: cd deploy-repo - # Only update stable directory + # Update stable directory rm -rf stable mkdir -p stable cp -r ../../original_docs/docs/html/* stable/ - # Create index.html redirection + # Regenerate the main index.html to include the latest tag version echo '' > index.html echo '' >> index.html echo '' >> index.html @@ -82,16 +82,47 @@ jobs: echo '
  • Stable (master branch)
  • ' >> index.html echo '
  • Latest (test branch)
  • ' >> index.html echo '
  • Tag versions
  • ' >> index.html + echo ' ' >> index.html + echo '

    Recent tag versions:

    ' >> index.html + echo '
      ' >> index.html + + # Regenerate the list of recent tag versions (last 5) + for dir in $(ls -1 versions/ 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V -r | head -5); do + echo "
    • Version $dir
    • " >> index.html + done + echo '
    ' >> index.html echo '' >> index.html echo '' >> index.html + # Also update versions/index.html to ensure that the list of all versions is up to date + echo '' > versions/index.html + echo '' >> versions/index.html + echo '' >> versions/index.html + echo ' Versioned Documentation' >> versions/index.html + echo '' >> versions/index.html + echo '' >> versions/index.html + echo '

    Versioned Documentation

    ' >> versions/index.html + echo '

    Select a version:

    ' >> versions/index.html + echo '
      ' >> versions/index.html + + # List all versions (from newest to oldest) + for dir in $(ls -1 versions/ 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V -r); do + echo "
    • Version $dir
    • " >> versions/index.html + done + + echo '
    ' >> versions/index.html + echo '

    Stable (master branch)

    ' >> versions/index.html + echo '

    Latest (test branch)

    ' >> versions/index.html + echo '' >> versions/index.html + echo '' >> versions/index.html + # Submit and push git add . if git diff-index --quiet HEAD --; then echo "No changes to deploy" else - git commit -m "Deploy ${{ steps.version.outputs.docs-version }} documentation from ${{ github.sha }}" + git commit -m "Deploy stable documentation from ${{ github.sha }} and update version lists" git push origin master - echo "✅ Stable documentation deployed successfully" + echo "✅ Stable documentation deployed successfully with updated version lists" fi \ No newline at end of file From 82e7d9daff43c825bbf67e2f01bf9f0dda575dbe Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sun, 5 Oct 2025 10:17:35 +0800 Subject: [PATCH 05/81] ci: Add workflow trigger conditions --- .github/workflows/deploy-docs-latest.yml | 1 + .github/workflows/deploy-docs-stable.yml | 1 + .github/workflows/deploy-docs-tags.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/deploy-docs-latest.yml b/.github/workflows/deploy-docs-latest.yml index fbf347a..a136c01 100644 --- a/.github/workflows/deploy-docs-latest.yml +++ b/.github/workflows/deploy-docs-latest.yml @@ -8,6 +8,7 @@ on: jobs: build-and-deploy: + if: github.repository == 'FrozenLemonTee/original' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/deploy-docs-stable.yml b/.github/workflows/deploy-docs-stable.yml index 7c8471f..53b867b 100644 --- a/.github/workflows/deploy-docs-stable.yml +++ b/.github/workflows/deploy-docs-stable.yml @@ -8,6 +8,7 @@ on: jobs: build-and-deploy: + if: github.repository == 'FrozenLemonTee/original' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/deploy-docs-tags.yml b/.github/workflows/deploy-docs-tags.yml index c56feac..2666f9c 100644 --- a/.github/workflows/deploy-docs-tags.yml +++ b/.github/workflows/deploy-docs-tags.yml @@ -9,6 +9,7 @@ on: jobs: build-and-deploy: + if: github.repository == 'FrozenLemonTee/original' runs-on: ubuntu-latest steps: From 3b0505445882a8288cb2653ef03af1b7c8affbd1 Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sun, 5 Oct 2025 10:17:58 +0800 Subject: [PATCH 06/81] ci: Show test details --- .github/workflows/full-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/full-tests.yml b/.github/workflows/full-tests.yml index 79ca7db..a175a66 100644 --- a/.github/workflows/full-tests.yml +++ b/.github/workflows/full-tests.yml @@ -56,7 +56,7 @@ jobs: - name: Run tests run: | - cd build && ctest --output-on-failure + cd build && ctest --verbose --output-on-failure windows-tests: runs-on: windows-latest @@ -75,4 +75,4 @@ jobs: - name: Run tests run: | - cd build && ctest -C ${{ matrix.build_type }} --output-on-failure \ No newline at end of file + cd build && ctest --verbose -C ${{ matrix.build_type }} --output-on-failure \ No newline at end of file From 7720132ce7d3b23eebd4223c3aef13837420ba29 Mon Sep 17 00:00:00 2001 From: frozenlemontee Date: Sun, 5 Oct 2025 10:18:19 +0800 Subject: [PATCH 07/81] ci: Add trigger condition --- .github/workflows/deploy-docs-stable.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy-docs-stable.yml b/.github/workflows/deploy-docs-stable.yml index 53b867b..1b88f99 100644 --- a/.github/workflows/deploy-docs-stable.yml +++ b/.github/workflows/deploy-docs-stable.yml @@ -5,6 +5,8 @@ name: Deploy Documentation - Stable on: push: branches: [ master ] + tags: + - 'v*.*.*' jobs: build-and-deploy: From aff72330a227e1926872607bb46e5f7c7e95a835 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:48:39 +0800 Subject: [PATCH 08/81] feat: Add conversion method to DWORD milliseconds --- src/vibrant/zeit.h | 50 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/vibrant/zeit.h b/src/vibrant/zeit.h index bf23e97..02328b1 100644 --- a/src/vibrant/zeit.h +++ b/src/vibrant/zeit.h @@ -1,5 +1,12 @@ #ifndef ORIGINAL_ZEIT_H #define ORIGINAL_ZEIT_H + +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG +#include +#elif ORIGINAL_COMPILER_MSVC +#include "minwindef.h" +#endif + #include #include "config.h" #include "comparable.h" @@ -7,9 +14,6 @@ #include "printable.h" #include "error.h" #include -#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG -#include -#endif /** * @file zeit.h @@ -156,6 +160,8 @@ namespace original { * into a unified duration value in nanoseconds. */ explicit duration(const timespec& ts); +#elif ORIGINAL_COMPILER_MSVC + explicit duration(DWORD milliseconds); #endif /// Default copy constructor @@ -219,6 +225,10 @@ namespace original { explicit operator timespec() const; timespec toTimespec() const; +#elif ORIGINAL_COMPILER_MSVC + explicit operator DWORD() const; + + DWORD toDWMilliseconds() const; #endif /** @@ -403,6 +413,8 @@ namespace original { * @note The conversion computes the total nanoseconds from ts.tv_sec and ts.tv_nsec. */ explicit point(const timespec& ts); +#elif ORIGINAL_COMPILER_MSVC + explicit point(DWORD milliseconds); #endif /** @@ -447,6 +459,10 @@ namespace original { explicit operator timespec() const; timespec toTimespec() const; +#elif ORIGINAL_COMPILER_MSVC + explicit operator DWORD() const; + + DWORD toDWMilliseconds() const; #endif /** @@ -1107,6 +1123,9 @@ inline original::time::duration::duration(const time_val_type val, const unit un #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::time::duration::duration(const timespec& ts) : nano_seconds_(ts.tv_sec * FACTOR_SECOND + ts.tv_nsec) {} +#elif ORIGINAL_COMPILER_MSVC +inline original::time::duration::duration(const DWORD milliseconds) + : nano_seconds_(static_cast(milliseconds) * FACTOR_MILLISECOND) {} #endif inline original::time::duration::duration(duration&& other) noexcept : duration() { @@ -1191,6 +1210,16 @@ inline timespec original::time::duration::toTimespec() const { return static_cast(*this); } +#elif ORIGINAL_COMPILER_MSVC +inline original::time::duration::operator DWORD() const +{ + return static_cast(this->value()); +} + +inline DWORD original::time::duration::toDWMilliseconds() const +{ + return static_cast(*this); +} #endif inline original::time::duration& @@ -1359,7 +1388,7 @@ original::time::point::now() { gettimeofday(&tv, nullptr); time_val_type ns = tv.tv_sec * FACTOR_SECOND + tv.tv_usec * FACTOR_MICROSECOND; return point(ns, NANOSECOND); -#else +#elif ORIGINAL_COMPILER_MSVC // Other implements not complete return point(); #endif @@ -1374,6 +1403,9 @@ inline original::time::point::point(duration d) #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::time::point::point(const timespec& ts) : nano_since_epoch_(ts) {} +#elif ORIGINAL_COMPILER_MSVC +inline original::time::point::point(const DWORD milliseconds) + : nano_since_epoch_(milliseconds) {} #endif inline original::time::time_val_type @@ -1414,6 +1446,16 @@ inline timespec original::time::point::toTimespec() const { return static_cast(*this); } +#elif ORIGINAL_COMPILER_MSVC +inline original::time::point::operator DWORD() const +{ + return static_cast(this->nano_since_epoch_); +} + +inline DWORD original::time::point::toDWMilliseconds() const +{ + return static_cast(*this); +} #endif inline original::time::point& From 8af067b662b6b7fd26f857d4caeefc0c0e29e1c0 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:49:22 +0800 Subject: [PATCH 09/81] chore: Add more excluded directories --- .gitignore | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 5b69209..6b24f6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ cmake-build-debug/ .idea/ -test.exe -original.zip -original.rar build/ install/ .vs/ +.vscode/ out/ -original/ \ No newline at end of file +original/ + +test.exe +original.zip +original.rar \ No newline at end of file From 0ef54e037b0f1d35edf4b7e53d7954d16b058fa1 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:50:30 +0800 Subject: [PATCH 10/81] refactor: Optimize precompiled macro code blocks --- src/vibrant/atomic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 37d482d..72f8f3a 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -310,7 +310,9 @@ namespace original { auto makeAtomic(TYPE value); } // namespace original +#endif +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG template original::atomicImpl::atomicImpl() { std::memset(this->data_, byte{}, sizeof(TYPE)); From 3b4bf1a36e588ba207abe84be5b9aad6541787ac Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:51:49 +0800 Subject: [PATCH 11/81] chore: Add platform setting for Visual Studio generator --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c8993b..8e2bc12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,14 @@ # CMakeLists.txt Main cmake_minimum_required(VERSION 3.31) +if(CMAKE_GENERATOR MATCHES "Visual Studio" OR CMAKE_GENERATOR MATCHES "Ninja Multi-Config") + set(CMAKE_GENERATOR_PLATFORM x64 CACHE STRING "Platform" FORCE) +endif() project(original LANGUAGES CXX) set(ORIGINAL_VERSION 0.1.5) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_CXX_EXTENSIONS OFF) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (default Release)" FORCE) endif() From 1d241e89b41ba8cd484ca8b8256a1ccada67475b Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:52:27 +0800 Subject: [PATCH 12/81] feat: Add wThread for msvc --- src/vibrant/thread.h | 162 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 5 deletions(-) diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index 7653a3d..10bef02 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -1,9 +1,14 @@ #ifndef THREAD_H #define THREAD_H +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG +#include "pthread.h" +#elif ORIGINAL_COMPILER_MSVC +#include "Winbase.h" +#endif + #include "error.h" #include "functional" -#include "pthread.h" #include "ownerPtr.h" #include "zeit.h" @@ -140,6 +145,7 @@ namespace original { std::string toString(bool enter) const override; }; +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG /** * @class pThread * @brief POSIX thread implementation @@ -231,6 +237,39 @@ namespace original { */ ~pThread() override; }; +#elif ORIGINAL_COMPILER_MSVC + class wThread final : public threadBase { + HANDLE handle; + bool is_joinable; + + [[nodiscard]] bool valid() const override; + public: + explicit wThread(); + + template + explicit wThread(Callback c, ARGS&& args...); + + wThread(wThread&& other) noexcept; + + wThread& operator=(wThread&& other) noexcept; + + [[nodiscard]] ul_integer id() const override; + + [[nodiscard]] bool joinable() const override; + + integer compareTo(const wThread &other) const override; + + u_integer toHash() const noexcept override; + + std::string className() const override; + + void join() override; + + void detach() override; + + ~wThread() override; + }; +#endif /** * @class thread @@ -261,7 +300,11 @@ namespace original { * @see original::thread::joinPolicy */ class thread final : public threadBase { + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG pThread thread_; ///< Underlying thread implementation + #elif ORIGINAL_COMPILER_MSVC + wThread thread_; + #endif bool will_join; ///< Join policy flag /** @@ -335,6 +378,7 @@ namespace original { template explicit thread(Callback c, joinPolicy policy, ARGS&&... args); +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG /** * @brief Construct a thread from an existing pThread with a join policy * @param p_thread The POSIX thread wrapper to take ownership of @@ -342,6 +386,9 @@ namespace original { * @post Takes ownership of the thread and applies the specified join policy */ explicit thread(pThread p_thread, joinPolicy policy = AUTO_JOIN); +#elif ORIGINAL_COMPILER_MSVC + explicit thread(wThread w_thread, joinPolicy policy = AUTO_JOIN); +#endif thread(const thread&) = delete; ///< Deleted copy constructor thread& operator=(const thread&) = delete; ///< Deleted copy assignment @@ -457,7 +504,7 @@ std::string original::threadBase::toString(bool enter) const { ss << "\n"; return ss.str(); } - +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::pThread::pThread() : handle(), is_joinable() {} template @@ -567,6 +614,103 @@ inline original::pThread::~pThread() } } } +#elif ORIGINAL_COMPILER_MSVC +inline bool original::wThread::valid() const +{ + return this->handle != HANDLE{}; +} + +inline original::wThread::wThread() : handle(), is_joinable() {} + +template +original::wThread::wThread(Callback c, ARGS&& args, ...) : handle(), is_joinable(true) +{ + auto bound_lambda = + [func = std::forward(c), ...lambda_args = std::forward(args)]() mutable { + std::invoke(std::move(func), std::move(lambda_args)...); + }; + + using bound_callback = decltype(bound_lambda); + using bound_thread_data = threadData; + + auto task = new bound_thread_data(std::move(bound_lambda)); + + this->handle = CreateThread(nullptr, 0, task, nullptr, 0, nullptr); +} + +inline original::wThread::wThread(wThread&& other) noexcept : wThread() +{ + this->operator=(std::move(other)); +} + +inline original::wThread& original::wThread::operator=(wThread&& other) noexcept +{ + if (this == &other) { + return *this; + } + + if (this->is_joinable && this->valid()) { + CloseHandle(this->handle); + } + + this->handle = other.handle; + other.handle = {}; + this->is_joinable = other.is_joinable; + other.is_joinable = false; + return *this; +} + +inline original::ul_integer original::wThread::id() const +{ + ul_integer id = 0; + std::memcpy(&id, &this->handle, sizeof(HANDLE)); + return id; +} + +inline bool original::wThread::joinable() const +{ + return this->is_joinable; +} + +inline original::integer original::wThread::compareTo(const wThread& other) const +{ + if (this->id() != other.id()) + return this->id() > other.id() ? 1 : -1; + return 0; +} + +inline original::u_integer original::wThread::toHash() const noexcept +{ + return hash::hashFunc(this->id()); +} + +inline std::string original::wThread::className() const +{ + return "wThread"; +} + +inline void original::wThread::join() +{ + WaitForSingleObject(this->handle, INFINITE); +} + +inline void original::wThread::detach() +{ + CloseHandle(this->handle); +} + +inline original::wThread::~wThread() +{ + if (this->is_joinable) { + try { + this->detach(); + } catch (...) { + std::cerr << "Fatal error in wThread destructor" << std::endl; + std::terminate(); + } + } +} +#endif inline bool original::thread::valid() const { @@ -576,9 +720,12 @@ inline bool original::thread::valid() const inline original::ul_integer original::thread::thisId() { ul_integer id = 0; -#ifdef ORIGINAL_COMPILER_GCC +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG auto handle = pthread_self(); std::memcpy(&id, &handle, sizeof(pthread_t)); +#elif ORIGINAL_COMPILER_MSVC + const auto handle = GetCurrentThreadId(); + std::memcpy(&id, &handle, sizeof(HANDLE)); #endif return id; } @@ -603,8 +750,8 @@ inline void original::thread::sleep(const time::duration& d) throw sysError("Failed to sleep thread (clock_nano-sleep returned " + formatString(ret) + ", errno: " + std::to_string(errno) + ")"); } -#else - ::Sleep(static_cast((d.value() + time::FACTOR_MILLISECOND - 1) / time::FACTOR_MILLISECOND)); +#elif ORIGINAL_COMPILER_MSVC + Sleep(static_cast((d.value() + time::FACTOR_MILLISECOND - 1) / time::FACTOR_MILLISECOND)); #endif } @@ -619,8 +766,13 @@ template original::thread::thread(Callback c, const joinPolicy policy, ARGS&&... args) : thread_(std::forward(c), std::forward(args)...), will_join(policy == AUTO_JOIN) {} +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::thread::thread(pThread p_thread, const joinPolicy policy) : thread_(std::move(p_thread)), will_join(policy == AUTO_JOIN) {} +#elif ORIGINAL_COMPILER_MSVC +inline original::thread::thread(wThread w_thread, const joinPolicy policy) + : thread_(std::move(w_thread)), will_join(policy == AUTO_JOIN) {} +#endif inline original::thread::thread(thread&& other) noexcept : thread_(std::move(other.thread_)), will_join(true) {} From b503fbdf71fbde860d1d47be727ff38a14b37ead Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:52:49 +0800 Subject: [PATCH 13/81] feat: Add wMutex for msvc --- src/vibrant/mutex.h | 89 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/src/vibrant/mutex.h b/src/vibrant/mutex.h index d280d61..f37fcf8 100644 --- a/src/vibrant/mutex.h +++ b/src/vibrant/mutex.h @@ -1,7 +1,12 @@ #ifndef MUTEX_H #define MUTEX_H +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" +#elif ORIGINAL_COMPILER_MSVC +#include "synchapi.h" +#endif + #include "error.h" #include "tuple.h" #include @@ -28,7 +33,7 @@ namespace original { * Derived classes must implement all pure virtual methods. */ class mutexBase { - protected: + public: /** * @brief Locks the mutex, blocking if necessary * @throws sysError if the lock operation fails @@ -54,7 +59,6 @@ namespace original { */ [[nodiscard]] virtual ul_integer id() const = 0; - public: /// Default constructor explicit mutexBase() = default; @@ -142,6 +146,7 @@ namespace original { virtual ~lockGuard() = default; }; +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG /** * @class pMutex * @brief POSIX thread mutex implementation @@ -151,7 +156,7 @@ namespace original { * and cleanup. */ class pMutex final : public mutexBase { - pthread_mutex_t mutex_; ///< Internal POSIX mutex handle + pthread_mutex_t mutex_{}; ///< Internal POSIX mutex handle public: /// Native handle type (pthread_mutex_t) using native_handle = pthread_mutex_t; @@ -205,6 +210,31 @@ namespace original { */ ~pMutex() override; }; +#elif ORIGINAL_COMPILER_MSVC + class wMutex final : public mutexBase { + CRITICAL_SECTION cs_; + public: + using native_handle = CRITICAL_SECTION; + + explicit wMutex(); + + wMutex(wMutex&&) = delete; + + wMutex& operator=(wMutex&&) = delete; + + [[nodiscard]] ul_integer id() const override; + + [[nodiscard]] void* nativeHandle() noexcept override; + + void lock() override; + + bool tryLock() override; + + void unlock() override; + + ~wMutex() override; + }; +#endif /** * @class uniqueLock @@ -214,17 +244,17 @@ namespace original { * with various locking policies. */ class uniqueLock final : public lockGuard { - pMutex& p_mutex_; ///< Reference to managed mutex + mutexBase& mutex_; ///< Reference to managed mutex bool is_locked; ///< Current lock state public: /** * @brief Constructs a uniqueLock with specified policy - * @param p_mutex Mutex to manage + * @param mutex Mutex to manage * @param policy Locking policy (default: AUTO_LOCK) * @throws sysError if locking fails */ - explicit uniqueLock(pMutex& p_mutex, lockPolicy policy = AUTO_LOCK); + explicit uniqueLock(mutexBase& mutex, lockPolicy policy = AUTO_LOCK); /// Deleted move constructor uniqueLock(uniqueLock&&) = delete; @@ -352,6 +382,7 @@ namespace original { }; } +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::pMutex::pMutex() : mutex_{} { if (const int code = pthread_mutex_init(&this->mutex_, nullptr); code != 0){ @@ -401,9 +432,45 @@ inline original::pMutex::~pMutex() { std::terminate(); } } +#elif ORIGINAL_COMPILER_MSVC +inline original::wMutex::wMutex() : cs_{} +{ + InitializeCriticalSection(&this->cs_); +} + +inline original::ul_integer original::wMutex::id() const +{ + return reinterpret_cast(&this->cs_); +} + +inline void* original::wMutex::nativeHandle() noexcept +{ + return &this->cs_; +} + +inline void original::wMutex::lock() +{ + EnterCriticalSection(&this->cs_); +} + +inline bool original::wMutex::tryLock() +{ + return TryEnterCriticalSection(&this->cs_) != 0; +} + +inline void original::wMutex::unlock() +{ + LeaveCriticalSection(&this->cs_); +} + +inline original::wMutex::~wMutex() +{ + DeleteCriticalSection(&this->cs_); +} +#endif -inline original::uniqueLock::uniqueLock(pMutex& p_mutex, lockPolicy policy) - : p_mutex_(p_mutex), is_locked(false) { +inline original::uniqueLock::uniqueLock(mutexBase& mutex, lockPolicy policy) + : mutex_(mutex), is_locked(false) { switch (policy) { case MANUAL_LOCK: break; @@ -426,7 +493,7 @@ inline void original::uniqueLock::lock() { if (this->is_locked) throw sysError("Cannot lock uniqueLock: already locked"); - this->p_mutex_.lock(); + this->mutex_.lock(); this->is_locked = true; } @@ -434,13 +501,13 @@ inline bool original::uniqueLock::tryLock() { if (this->is_locked) throw sysError("Cannot try-lock uniqueLock: already locked"); - this->is_locked = this->p_mutex_.tryLock(); + this->is_locked = this->mutex_.tryLock(); return this->is_locked; } inline void original::uniqueLock::unlock() { if (this->is_locked){ - this->p_mutex_.unlock(); + this->mutex_.unlock(); this->is_locked = false; } } From 5696ddfdeae2edd8a249f649f2abfff0bc3f2bc1 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:53:03 +0800 Subject: [PATCH 14/81] feat: Add wCondition for msvc --- src/vibrant/condition.h | 80 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index 02309ec..3c08da3 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -1,5 +1,12 @@ #ifndef CONDITION_H #define CONDITION_H + +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG +#include +#elif ORIGINAL_COMPILER_MSVC +#include "WinBase.h" +#endif + #include "mutex.h" #include "zeit.h" @@ -118,6 +125,7 @@ namespace original conditionBase& operator=(const conditionBase&) = delete; }; +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG /** * @class pCondition * @brief POSIX condition variable implementation @@ -176,8 +184,29 @@ namespace original */ ~pCondition() override; }; -} +#elif ORIGINAL_COMPILER_MSVC + class wCondition final : public conditionBase + { + CONDITION_VARIABLE cond_; + public: + using conditionBase::wait; + using conditionBase::waitFor; + + explicit wCondition(); + + void wait(mutexBase& mutex) override; + + bool waitFor(mutexBase& mutex, time::duration d) override; + + void notify() override; + + void notifyAll() override; + + ~wCondition() override; + }; +#endif +} template void original::conditionBase::wait(mutexBase& mutex, Pred predicate) noexcept(noexcept(predicate())) { while (!predicate()){ @@ -211,6 +240,7 @@ inline void original::conditionBase::notifySome(const u_integer n) { } } +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG inline original::pCondition::pCondition() : cond_{} { if (const int code = pthread_cond_init(&this->cond_, nullptr); code != 0) @@ -269,5 +299,53 @@ inline original::pCondition::~pCondition() << code << ")" << std::endl; } } +#elif ORIGINAL_COMPILER_MSVC +inline original::wCondition::wCondition() : cond_{} +{ + InitializeConditionVariable(&this->cond_); +} + +inline void original::wCondition::wait(mutexBase& mutex) +{ + const auto w_mutex = dynamic_cast(&mutex); + if (!w_mutex) { + throw valueError("Invalid mutex type for condition variable: must be wMutex"); + } + if (const auto handle = static_cast(w_mutex->nativeHandle()); + !SleepConditionVariableCS(&this->cond_, handle, INFINITE)) { + throw sysError("Failed to wait on condition variable (SleepConditionVariableCS returned error " + + printable::formatString(GetLastError())); + } +} + +inline bool original::wCondition::waitFor(mutexBase& mutex, const time::duration d) +{ + const auto w_mutex = dynamic_cast(&mutex); + if (!w_mutex) { + throw valueError("Invalid mutex type for condition variable: must be wMutex"); + } + + const auto handle = static_cast(w_mutex->nativeHandle()); + if (const auto timeout_ms = d.toDWMilliseconds(); !SleepConditionVariableCS(&this->cond_, handle, timeout_ms)) { + const DWORD error = GetLastError(); + if (error == ERROR_TIMEOUT) { + return false; + } + throw sysError("Failed to timed wait on condition variable (SleepConditionVariableCS returned error " + + printable::formatString(error)); + } + return true; +} + +inline void original::wCondition::notify() +{ + WakeConditionVariable(&this->cond_); +} + +inline void original::wCondition::notifyAll() +{ + WakeAllConditionVariable(&this->cond_); +} +#endif #endif //CONDITION_H From f89315fe4a8057660e5ccbecbfc79a8d1e9e20a8 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:53:41 +0800 Subject: [PATCH 15/81] refactor: Add missing platform marcos definitions --- src/core/config.h | 154 ++++++++++++++++++++++++++++++---------------- 1 file changed, 101 insertions(+), 53 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index b373d2e..741358d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -17,22 +17,37 @@ * @{ */ +// Initialize all platform macros to false +#define ORIGINAL_PLATFORM_WINDOWS 0 +#define ORIGINAL_PLATFORM_WINDOWS_32 0 +#define ORIGINAL_PLATFORM_WINDOWS_64 0 +#define ORIGINAL_PLATFORM_LINUX 0 +#define ORIGINAL_PLATFORM_MACOS 0 +#define ORIGINAL_PLATFORM_UNIX 0 +#define ORIGINAL_PLATFORM_UNKNOWN 0 + +// Override based on actual platform detection #if defined(_WIN32) || defined(_WIN64) -#define ORIGINAL_PLATFORM_WINDOWS 1 -#ifdef _WIN64 -#define ORIGINAL_PLATFORM_WINDOWS_64 1 -#elif -#define ORIGINAL_PLATFORM_WINDOWS_32 1 -#else - #define ORIGINAL_PLATFORM_WINDOWS 0 -#endif + #undef ORIGINAL_PLATFORM_WINDOWS + #define ORIGINAL_PLATFORM_WINDOWS 1 + #ifdef _WIN64 + #undef ORIGINAL_PLATFORM_WINDOWS_64 + #define ORIGINAL_PLATFORM_WINDOWS_64 1 + #else + #undef ORIGINAL_PLATFORM_WINDOWS_32 + #define ORIGINAL_PLATFORM_WINDOWS_32 1 + #endif #elif defined(__linux__) -#define ORIGINAL_PLATFORM_LINUX 1 + #undef ORIGINAL_PLATFORM_LINUX + #define ORIGINAL_PLATFORM_LINUX 1 #elif defined(__APPLE__) && defined(__MACH__) + #undef ORIGINAL_PLATFORM_MACOS #define ORIGINAL_PLATFORM_MACOS 1 #elif defined(__unix__) + #undef ORIGINAL_PLATFORM_UNIX #define ORIGINAL_PLATFORM_UNIX 1 #else + #undef ORIGINAL_PLATFORM_UNKNOWN #define ORIGINAL_PLATFORM_UNKNOWN 1 #endif /** @} */ // end of PlatformDetection group @@ -42,16 +57,28 @@ * @brief Macros for identifying the compiler being used * @{ */ + +// Initialize all compiler macros to false +#define ORIGINAL_COMPILER_CLANG 0 +#define ORIGINAL_COMPILER_GCC 0 +#define ORIGINAL_COMPILER_MSVC 0 +#define ORIGINAL_COMPILER_UNKNOWN 0 + +// Override based on actual compiler detection #if defined(__clang__) -#define ORIGINAL_COMPILER_CLANG 1 + #undef ORIGINAL_COMPILER_CLANG + #define ORIGINAL_COMPILER_CLANG 1 #define ORIGINAL_COMPILER_VERSION __clang_major__.__clang_minor__.__clang_patchlevel__ #elif defined(__GNUC__) || defined(__GNUG__) -#define ORIGINAL_COMPILER_GCC 1 -#define ORIGINAL_COMPILER_VERSION __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__ + #undef ORIGINAL_COMPILER_GCC + #define ORIGINAL_COMPILER_GCC 1 + #define ORIGINAL_COMPILER_VERSION __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__ #elif defined(_MSC_VER) -#define ORIGINAL_COMPILER_MSVC 1 + #undef ORIGINAL_COMPILER_MSVC + #define ORIGINAL_COMPILER_MSVC 1 #define ORIGINAL_COMPILER_VERSION _MSC_VER #else + #undef ORIGINAL_COMPILER_UNKNOWN #define ORIGINAL_COMPILER_UNKNOWN 1 #endif /** @} */ // end of CompilerDetection group @@ -228,50 +255,71 @@ namespace original { * @{ */ - /** - * @brief Unsigned 8-bit integer type (byte) - * @details Typically used for raw byte manipulation and binary data handling. - * @note Range: 0 to 255 - * @note Equivalent to std::uint8_t - */ - using byte = std::uint8_t; + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + /** + * @brief Unsigned 8-bit integer type (byte) + * @details Typically used for raw byte manipulation and binary data handling. + * @note Range: 0 to 255 + * @note Equivalent to std::uint8_t + */ + using byte = std::uint8_t; + #elif ORIGINAL_COMPILER_MSVC + using byte = uint8_t; + #endif - /** - * @brief Signed 8-bit integer type - * @details Used for small signed numeric values. - * @note Range: -128 to 127 - * @note Equivalent to std::int8_t - */ - using s_byte = std::int8_t; - /** - * @brief 64-bit signed integer type for arithmetic operations - * @details Primary type for most arithmetic operations where large range is needed. - * @note Range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 - * @note Use this for calculations that may require large numbers - * @note Equivalent to std::int64_t - */ - using integer = std::int64_t; + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + /** + * @brief Signed 8-bit integer type + * @details Used for small signed numeric values. + * @note Range: -128 to 127 + * @note Equivalent to std::int8_t + */ + using s_byte = std::int8_t; + #elif ORIGINAL_COMPILER_MSVC + using s_byte = int8_t; + #endif - /** - * @brief 32-bit unsigned integer type for sizes and indexes - * @details Used for array indexing, sizes, and counts where negative values are not needed. - * @note Range: 0 to 4,294,967,295 - * @warning Not suitable for very large containers (>4GB) - * @note Equivalent to std::uint32_t - */ - using u_integer = std::uint32_t; + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + /** + * @brief 64-bit signed integer type for arithmetic operations + * @details Primary type for most arithmetic operations where large range is needed. + * @note Range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 + * @note Use this for calculations that may require large numbers + * @note Equivalent to std::int64_t + */ + using integer = std::int64_t; + #elif ORIGINAL_COMPILER_MSVC + using integer = int64_t; + #endif - /** - * @brief 64-bit unsigned integer type - * @details Large unsigned integer type for big sizes and counters. - * Guaranteed to be exactly 64 bits wide across all platforms. - * @note Range: 0 to 18,446,744,073,709,551,615 - * @note Preferred for: Large containers, filesystem sizes, big counters - * @see u_integer For smaller unsigned needs - * @note Equivalent to std::uint64_t - */ - using ul_integer = std::uint64_t; + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + /** + * @brief 32-bit unsigned integer type for sizes and indexes + * @details Used for array indexing, sizes, and counts where negative values are not needed. + * @note Range: 0 to 4,294,967,295 + * @warning Not suitable for very large containers (>4GB) + * @note Equivalent to std::uint32_t + */ + using u_integer = std::uint32_t; + #elif ORIGINAL_COMPILER_MSVC + using u_integer = uint32_t; + #endif + + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + /** + * @brief 64-bit unsigned integer type + * @details Large unsigned integer type for big sizes and counters. + * Guaranteed to be exactly 64 bits wide across all platforms. + * @note Range: 0 to 18,446,744,073,709,551,615 + * @note Preferred for: Large containers, filesystem sizes, big counters + * @see u_integer For smaller unsigned needs + * @note Equivalent to std::uint64_t + */ + using ul_integer = std::uint64_t; + #elif ORIGINAL_COMPILER_MSVC + using ul_integer = uint64_t; + #endif /** * @brief Double-precision floating-point type From 9884d4134590b36e28503c734c97c3ba08f16403 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Wed, 8 Oct 2025 19:54:17 +0800 Subject: [PATCH 16/81] refactor: Add missing template arg for msvc --- test/other/test1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/other/test1.cpp b/test/other/test1.cpp index d3c62be..bb7b8b4 100644 --- a/test/other/test1.cpp +++ b/test/other/test1.cpp @@ -11,7 +11,7 @@ int main(){ std::printf("%s", arr1.toString(true).c_str()); original::array arr2 = {1, 4, 5, 3, 8}; std::printf("%s", arr2.toString(true).c_str()); - std::printf("max(5,3):%d\n", original::max(5, 3)); + std::printf("max(5,3):%d\n", original::max(5, 3)); auto arr3 = arr2; std::printf("arr3:%p, arr2:%p\n", &arr3, &arr2); std::printf("arr3:%s\narr2:%s\n", arr3.toString(false).c_str(), arr2.toString(false).c_str()); From 05ec5cb1df7d3e0e7000b4976fa3393725dcb113 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 00:13:31 +0800 Subject: [PATCH 17/81] refactor: Use correct header to avoid architecture not defined error --- src/vibrant/atomic.h | 8 +++++++- src/vibrant/condition.h | 4 +++- src/vibrant/mutex.h | 4 +++- src/vibrant/thread.h | 4 +++- src/vibrant/zeit.h | 3 ++- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 72f8f3a..6b7684d 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -1,8 +1,14 @@ #ifndef ORIGINAL_ATOMIC_H #define ORIGINAL_ATOMIC_H -#include +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include +#elif ORIGINAL_COMPILER_MSVC +#define WIN32_LEAN_AND_MEAN +#endif + + +#include #include "optional.h" #include "config.h" #include "mutex.h" diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index 3c08da3..c4944bf 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -4,7 +4,9 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC -#include "WinBase.h" +#define WIN32_LEAN_AND_MEAN +#include +#include #endif #include "mutex.h" diff --git a/src/vibrant/mutex.h b/src/vibrant/mutex.h index f37fcf8..4cb2465 100644 --- a/src/vibrant/mutex.h +++ b/src/vibrant/mutex.h @@ -4,7 +4,9 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" #elif ORIGINAL_COMPILER_MSVC -#include "synchapi.h" +#define WIN32_LEAN_AND_MEAN +#include +#include #endif #include "error.h" diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index 10bef02..a142430 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -4,7 +4,9 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" #elif ORIGINAL_COMPILER_MSVC -#include "Winbase.h" +#define WIN32_LEAN_AND_MEAN +#include +#include #endif #include "error.h" diff --git a/src/vibrant/zeit.h b/src/vibrant/zeit.h index 02328b1..2289c68 100644 --- a/src/vibrant/zeit.h +++ b/src/vibrant/zeit.h @@ -4,7 +4,8 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC -#include "minwindef.h" +#define WIN32_LEAN_AND_MEAN +#include #endif #include From f8698c505c5780489ec16641d24bbd7c4cb868da Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 00:14:52 +0800 Subject: [PATCH 18/81] feat: Add declaration of atomic for msvc --- src/vibrant/atomic.h | 120 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 6b7684d..2d56e92 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -295,7 +295,117 @@ namespace original { template friend auto makeAtomic(T value); }; +#elif ORIGINAL_COMPILER_MSVC + enum class memOrder { + RELAXED, + ACQUIRE, + RELEASE, + ACQ_REL, + SEQ_CST, + }; + + template + constexpr bool isLockFreeType() noexcept; + + template + class atomicImpl; + + template + using atomic = atomicImpl()>; + + template + class atomicImpl + { + alignas(TYPE) volatile TYPE data_; + + public: + static constexpr auto RELAXED = memOrder::RELAXED; + static constexpr auto ACQUIRE = memOrder::ACQUIRE; + static constexpr auto RELEASE = memOrder::RELEASE; + static constexpr auto ACQ_REL = memOrder::ACQ_REL; + static constexpr auto SEQ_CST = memOrder::SEQ_CST; + + atomicImpl(const atomicImpl&) = delete; + atomicImpl(atomicImpl&&) = delete; + atomicImpl& operator=(const atomicImpl&) = delete; + atomicImpl& operator=(atomicImpl&&) = delete; + + static constexpr bool isLockFree() noexcept; + + void store(TYPE value, memOrder order = SEQ_CST); + + TYPE load(memOrder order = SEQ_CST) const noexcept; + + TYPE operator*() const noexcept; + + explicit operator TYPE() const noexcept; + + void operator=(TYPE value) noexcept; + + atomicImpl& operator+=(TYPE value) noexcept; + + atomicImpl& operator-=(TYPE value) noexcept; + + TYPE exchange(TYPE value, memOrder order = SEQ_CST) noexcept; + + bool exchangeCmp(TYPE& expected, TYPE desired, memOrder order = SEQ_CST) noexcept; + + ~atomicImpl() = default; + + template + friend auto makeAtomic(); + + template + friend auto makeAtomic(T value); + }; + + template + class atomicImpl + { + mutable wMutex mutex_; + alternative data_; + + public: + static constexpr auto RELAXED = memOrder::RELAXED; + static constexpr auto ACQUIRE = memOrder::ACQUIRE; + static constexpr auto RELEASE = memOrder::RELEASE; + static constexpr auto ACQ_REL = memOrder::ACQ_REL; + static constexpr auto SEQ_CST = memOrder::SEQ_CST; + + atomicImpl(const atomicImpl&) = delete; + atomicImpl(atomicImpl&&) = delete; + atomicImpl& operator=(const atomicImpl&) = delete; + atomicImpl& operator=(atomicImpl&&) = delete; + + static constexpr bool isLockFree() noexcept; + + void store(TYPE value, memOrder order = SEQ_CST); + + TYPE load(memOrder order = SEQ_CST) const noexcept; + + TYPE operator*() const noexcept; + + explicit operator TYPE() const noexcept; + + void operator=(TYPE value) noexcept; + + atomicImpl& operator+=(TYPE value) noexcept; + + atomicImpl& operator-=(TYPE value) noexcept; + + TYPE exchange(TYPE value, memOrder order = SEQ_CST) noexcept; + + bool exchangeCmp(TYPE& expected, TYPE desired, memOrder order = SEQ_CST) noexcept; + + ~atomicImpl() = default; + + template + friend auto makeAtomic(); + template + friend auto makeAtomic(T value); + }; +#endif // ==================== Factory Functions ==================== /** @@ -316,7 +426,6 @@ namespace original { auto makeAtomic(TYPE value); } // namespace original -#endif #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG template @@ -471,6 +580,14 @@ bool original::atomicImpl::exchangeCmp(TYPE& expected, const TYPE& d expected = *this->data_; return false; } +#elif ORIGINAL_COMPILER_MSVC + +template +constexpr bool original::isLockFreeType() noexcept { + return sizeof(TYPE) == 4 || sizeof(TYPE) == 8; +} + +#endif template auto original::makeAtomic() @@ -484,4 +601,3 @@ auto original::makeAtomic(TYPE value) return atomic{std::move(value)}; } #endif -#endif From e087325be90a110a1de802fc4f5e26b7f4586649 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 12:08:22 +0800 Subject: [PATCH 19/81] feat: Add condition tool some --- src/core/types.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/core/types.h b/src/core/types.h index 0a2f997..bcdd3f5 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -516,6 +516,23 @@ namespace original { c.pop_back(); }; + template + class some; + + template + class some + { + public: + using type = MATCH_TYPE; + }; + + template + class some + { + public: + using type = OTHER_TYPE; + }; + // ==================== Compile-time Index Sequences ==================== /** From a555bf43c998debb50aeec8d176cd9566cc9388c Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 12:09:02 +0800 Subject: [PATCH 20/81] feat: Add impl of atomicImpl for msvc --- src/vibrant/atomic.h | 141 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 2d56e92..29cd4f8 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -316,8 +316,13 @@ namespace original { template class atomicImpl { + using val_type = some; + alignas(TYPE) volatile TYPE data_; + atomicImpl(); + + explicit atomicImpl(TYPE value, memOrder order = SEQ_CST); public: static constexpr auto RELAXED = memOrder::RELAXED; static constexpr auto ACQUIRE = memOrder::ACQUIRE; @@ -587,6 +592,142 @@ constexpr bool original::isLockFreeType() noexcept { return sizeof(TYPE) == 4 || sizeof(TYPE) == 8; } +template +original::atomicImpl::atomicImpl() +{ + std::memset(this->data_, byte{}, sizeof(TYPE)); +} + +template +original::atomicImpl::atomicImpl(TYPE value, const memOrder order) +{ + this->store(value, order); +} + +template +constexpr bool +original::atomicImpl::isLockFree() noexcept +{ + return true; +} + +template +void original::atomicImpl::store(TYPE value, const memOrder order) +{ + switch (order) { + case memOrder::RELAXED: + this->data_ = value; + break; + case memOrder::RELEASE: + _WriteBarrier(); + this->data_ = value; + break; + case memOrder::SEQ_CST: + default: + if constexpr (sizeof(TYPE) == 4) { + InterlockedExchange(reinterpret_cast(&this->data_), static_cast(value)); + } else { + InterlockedExchange64(reinterpret_cast(&this->data_), static_cast(value)); + } + break; + } +} + +template +TYPE original::atomicImpl::load(const memOrder order) const noexcept +{ + TYPE value; + switch (order) { + case memOrder::RELAXED: + value = this->data_; + break; + case memOrder::ACQUIRE: + value = this->data_; + _ReadBarrier(); + break; + case memOrder::SEQ_CST: + default: + if constexpr (sizeof(TYPE) == 4) { + value = InterlockedCompareExchange( + reinterpret_cast(&this->data_), 0, 0); + } else { + value = InterlockedCompareExchange64( + reinterpret_cast(&this->data_), 0, 0); + } + break; + } + return value; +} + +template +TYPE original::atomicImpl::operator*() const noexcept +{ + return this->load(); +} + +template +original::atomicImpl::operator TYPE() const noexcept +{ + return this->load(); +} + +template +void original::atomicImpl::operator=(TYPE value) noexcept +{ + this->store(std::move(value)); +} + +template +original::atomicImpl& +original::atomicImpl::operator+=(TYPE value) noexcept +{ + if constexpr (sizeof(TYPE) == 4) { + InterlockedAdd(reinterpret_cast(&this->data_), static_cast(value)); + } else { + InterlockedAdd64(reinterpret_cast(&this->data_), static_cast(value)); + } + return *this; +} + +template +original::atomicImpl& +original::atomicImpl::operator-=(TYPE value) noexcept +{ + return *this += -value; +} + +template +TYPE original::atomicImpl::exchange(TYPE value, memOrder) noexcept +{ + if constexpr (sizeof(TYPE) == 4) { + return InterlockedExchange(reinterpret_cast(&this->data_), static_cast(value)); + } else { + return InterlockedExchange64(reinterpret_cast(&this->data_), static_cast(value)); + } +} + +template +bool original::atomicImpl::exchangeCmp(TYPE& expected, TYPE desired, memOrder) noexcept +{ + if constexpr (sizeof(TYPE) == 4) { + val_type old = InterlockedCompareExchange( + reinterpret_cast(&this->data_), + static_cast(desired), + static_cast(expected)); + const bool success = old == static_cast(expected); + if (!success) expected = static_cast(old); + return success; + } else { + val_type old = InterlockedCompareExchange64( + reinterpret_cast(&this->data_), + static_cast(desired), + static_cast(expected)); + const bool success = old == static_cast(expected); + if (!success) expected = static_cast(old); + return success; + } +} + #endif template From 26065a9686fb7ba4515ad30c8b08da258fc920e2 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 17:18:37 +0800 Subject: [PATCH 21/81] feat: Add alias some_t for some::type --- src/core/types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/types.h b/src/core/types.h index bcdd3f5..e3228cd 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -533,6 +533,9 @@ namespace original { using type = OTHER_TYPE; }; + template + using some_t = some::type; + // ==================== Compile-time Index Sequences ==================== /** From 8196d1b5a9fdefc3dcabdef16f2818fb50b5be0d Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Thu, 9 Oct 2025 17:19:29 +0800 Subject: [PATCH 22/81] feat: Add impl of atomicImpl for msvc --- src/vibrant/atomic.h | 111 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 29cd4f8..2636758 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -4,7 +4,6 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC -#define WIN32_LEAN_AND_MEAN #endif @@ -68,7 +67,7 @@ namespace original { */ template class atomicImpl { - alignas(TYPE) byte data_[sizeof(TYPE)]; ///< Properly aligned storage + alignas(TYPE) byte data_[sizeof(TYPE)]{}; ///< Properly aligned storage /** * @brief Default constructor (zero-initializes storage) @@ -132,7 +131,7 @@ namespace original { * @brief Assignment operator (atomically stores value) * @param value Value to store */ - void operator=(TYPE value) noexcept; + atomicImpl& operator=(TYPE value) noexcept; /** * @brief Atomic addition assignment @@ -252,7 +251,7 @@ namespace original { * @brief Assignment operator (atomically stores value) * @param value Value to store */ - void operator=(TYPE value) noexcept; + atomicImpl& operator=(TYPE value) noexcept; /** * @brief Atomic addition assignment @@ -316,9 +315,9 @@ namespace original { template class atomicImpl { - using val_type = some; + using val_type = some_t; - alignas(TYPE) volatile TYPE data_; + alignas(TYPE) volatile TYPE data_{}; atomicImpl(); @@ -345,7 +344,7 @@ namespace original { explicit operator TYPE() const noexcept; - void operator=(TYPE value) noexcept; + atomicImpl& operator=(TYPE value) noexcept; atomicImpl& operator+=(TYPE value) noexcept; @@ -370,6 +369,9 @@ namespace original { mutable wMutex mutex_; alternative data_; + atomicImpl() = default; + + explicit atomicImpl(TYPE value, memOrder order = RELEASE); public: static constexpr auto RELAXED = memOrder::RELAXED; static constexpr auto ACQUIRE = memOrder::ACQUIRE; @@ -392,7 +394,7 @@ namespace original { explicit operator TYPE() const noexcept; - void operator=(TYPE value) noexcept; + atomicImpl& operator=(TYPE value) noexcept; atomicImpl& operator+=(TYPE value) noexcept; @@ -473,9 +475,10 @@ original::atomicImpl::operator TYPE() const noexcept } template -void original::atomicImpl::operator=(TYPE value) noexcept +original::atomicImpl& original::atomicImpl::operator=(TYPE value) noexcept { this->store(std::move(value)); + return *this; } template @@ -544,9 +547,11 @@ original::atomicImpl::operator TYPE() const noexcept } template -void original::atomicImpl::operator=(TYPE value) noexcept +original::atomicImpl& +original::atomicImpl::operator=(TYPE value) noexcept { this->store(std::move(value)); + return *this; } template @@ -672,9 +677,11 @@ original::atomicImpl::operator TYPE() const noexcept } template -void original::atomicImpl::operator=(TYPE value) noexcept +original::atomicImpl& +original::atomicImpl::operator=(TYPE value) noexcept { this->store(std::move(value)); + return *this; } template @@ -711,7 +718,7 @@ bool original::atomicImpl::exchangeCmp(TYPE& expected, TYPE desired { if constexpr (sizeof(TYPE) == 4) { val_type old = InterlockedCompareExchange( - reinterpret_cast(&this->data_), + reinterpret_cast(&this->data_), static_cast(desired), static_cast(expected)); const bool success = old == static_cast(expected); @@ -728,6 +735,86 @@ bool original::atomicImpl::exchangeCmp(TYPE& expected, TYPE desired } } +template +original::atomicImpl::atomicImpl(TYPE value, memOrder) { + uniqueLock lock{this->mutex_}; + this->data_.set(value); +} + +template +constexpr bool original::atomicImpl::isLockFree() noexcept { + return false; +} + +template +void original::atomicImpl::store(TYPE value, memOrder) { + uniqueLock lock{this->mutex_}; + this->data_.set(value); +} + +template +TYPE original::atomicImpl::load(memOrder) const noexcept { + uniqueLock lock{this->mutex_}; + return *this->data_; +} + +template +TYPE original::atomicImpl::operator*() const noexcept +{ + return this->load(); +} + +template +original::atomicImpl::operator TYPE() const noexcept +{ + return this->load(); +} + +template +original::atomicImpl& +original::atomicImpl::operator=(TYPE value) noexcept +{ + this->store(std::move(value)); + return *this; +} + +template +original::atomicImpl& original::atomicImpl::operator+=(TYPE value) noexcept +{ + uniqueLock lock{this->mutex_}; + TYPE result = *this->data_ + value; + this->data_.set(result); + return *this; +} + +template +original::atomicImpl& original::atomicImpl::operator-=(TYPE value) noexcept +{ + uniqueLock lock{this->mutex_}; + TYPE result = *this->data_ - value; + this->data_.set(result); + return *this; +} + +template +TYPE original::atomicImpl::exchange(const TYPE& value, memOrder) noexcept { + uniqueLock lock{this->mutex_}; + TYPE result = *this->data_; + this->data_.set(value); + return result; +} + +template +bool original::atomicImpl::exchangeCmp(TYPE& expected, const TYPE& desired, memOrder) noexcept { + uniqueLock lock{this->mutex_}; + if (*this->data_ == expected) { + this->data_.set(desired); + return true; + } + expected = *this->data_; + return false; +} + #endif template From 61a7ee75aa0f03d53d6e0a8b4d5e12cd0fd0e554 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:10:22 +0800 Subject: [PATCH 23/81] test: Enable big object test --- test/unit_test/test_vibrant/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit_test/test_vibrant/CMakeLists.txt b/test/unit_test/test_vibrant/CMakeLists.txt index 54225eb..fcc8d6d 100644 --- a/test/unit_test/test_vibrant/CMakeLists.txt +++ b/test/unit_test/test_vibrant/CMakeLists.txt @@ -6,6 +6,11 @@ file(GLOB VIBRANT_TESTS "test_*.cpp") add_executable(vibrant_test ${VIBRANT_TESTS}) +if(MSVC) + target_compile_options(vibrant_test PRIVATE "/bigobj") + target_compile_options(vibrant_test PRIVATE "/Zc:inline") +endif() + target_link_libraries(vibrant_test PRIVATE GTest::gtest GTest::gmock GTest::gmock_main GTest::gtest_main) target_link_libraries(vibrant_test PRIVATE original) From cf476e847c1eb88ffc8f5aefe06a64a5ab5e8934 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:15:16 +0800 Subject: [PATCH 24/81] refactor: Rename to maximum --- src/core/allocator.h | 8 ++++---- src/core/maths.h | 4 ++-- test/other/test1.cpp | 2 +- test/other/test7.cpp | 3 ++- test/unit_test/test_core/test_maths.cpp | 16 ++++++++-------- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/core/allocator.h b/src/core/allocator.h index 5d666f7..271c614 100644 --- a/src/core/allocator.h +++ b/src/core/allocator.h @@ -488,15 +488,15 @@ original::objPoolAllocator& original::objPoolAllocator::operator+=(o if (this == &other) return *this; - auto size_class_count_max = max(this->size_class_count, other.size_class_count); - auto chunk_count_init_max = max(this->chunk_count_init, other.chunk_count_init); + auto size_class_count_max = maximum(this->size_class_count, other.size_class_count); + auto chunk_count_init_max = maximum(this->chunk_count_init, other.chunk_count_init); auto chunk_count_max = allocators::malloc(size_class_count_max); auto free_list_head_max = allocators::malloc(size_class_count_max); auto chunks_available_max = allocators::malloc(size_class_count_max); for (u_integer i = 0; i < size_class_count_max; i++) { if (i < this->size_class_count && i < other.size_class_count) { - chunk_count_max[i] = max(this->chunk_count[i], other.chunk_count[i]); + chunk_count_max[i] = maximum(this->chunk_count[i], other.chunk_count[i]); chunks_available_max[i] = this->chunks_available[i] + other.chunks_available[i]; auto cur_list_head_i = other.free_list_head[i]; if (cur_list_head_i) { @@ -597,7 +597,7 @@ TYPE* original::objPoolAllocator::allocate(const u_integer size) } if (!this->free_list_head[index] || this->chunks_available[index] * (static_cast(1) << index) < size) { - this->chunkAllocate(max(1, this->chunk_count[index]), index); + this->chunkAllocate(maximum(1, this->chunk_count[index]), index); } auto cur_ptr = this->free_list_head[index]; diff --git a/src/core/maths.h b/src/core/maths.h index b5299d0..4f348b5 100644 --- a/src/core/maths.h +++ b/src/core/maths.h @@ -79,7 +79,7 @@ TYPE abs(TYPE a); * @endcode */ template -TYPE max(TYPE a, TYPE b); +TYPE maximum(TYPE a, TYPE b); /** * @brief Returns the smaller of two given values. @@ -186,7 +186,7 @@ auto original::abs(TYPE a) -> TYPE } template -auto original::max(TYPE a, TYPE b) -> TYPE +auto original::maximum(TYPE a, TYPE b) -> TYPE { return a > b ? a : b; } diff --git a/test/other/test1.cpp b/test/other/test1.cpp index bb7b8b4..f0c6da7 100644 --- a/test/other/test1.cpp +++ b/test/other/test1.cpp @@ -11,7 +11,7 @@ int main(){ std::printf("%s", arr1.toString(true).c_str()); original::array arr2 = {1, 4, 5, 3, 8}; std::printf("%s", arr2.toString(true).c_str()); - std::printf("max(5,3):%d\n", original::max(5, 3)); + std::printf("maximum(5,3):%d\n", original::maximum(5, 3)); auto arr3 = arr2; std::printf("arr3:%p, arr2:%p\n", &arr3, &arr2); std::printf("arr3:%s\narr2:%s\n", arr3.toString(false).c_str(), arr2.toString(false).c_str()); diff --git a/test/other/test7.cpp b/test/other/test7.cpp index 264a965..5f83a96 100644 --- a/test/other/test7.cpp +++ b/test/other/test7.cpp @@ -3,12 +3,13 @@ #include "async.h" #include "singleton.h" #include "tasks.h" +#include "maths.h" #include "coroutines.h" #include "generators.h" original::array matrixAdd(const original::array& a, const original::array& b) { - const auto len = original::max(a.size(), b.size()); + const auto len = original::maximum(a.size(), b.size()); original::array result(len); for (original::integer i = 0; i < len; i++) { if (i < a.size()) diff --git a/test/unit_test/test_core/test_maths.cpp b/test/unit_test/test_core/test_maths.cpp index ea9da95..86476de 100644 --- a/test/unit_test/test_core/test_maths.cpp +++ b/test/unit_test/test_core/test_maths.cpp @@ -21,30 +21,30 @@ TEST(MathsTests, AbsDoubleNegative) { EXPECT_EQ(original::abs(-5.5), std::abs(-5.5)); } -// Tests for max +// Tests for maximum TEST(MathsTests, MaxInt) { - EXPECT_EQ(original::max(3, 5), std::max(3, 5)); + EXPECT_EQ(original::maximum(3, 5), std::max(3, 5)); } TEST(MathsTests, MaxDouble) { - EXPECT_EQ(original::max(3.5, 5.5), std::max(3.5, 5.5)); + EXPECT_EQ(original::maximum(3.5, 5.5), std::max(3.5, 5.5)); } TEST(MathsTests, MaxEqual) { - EXPECT_EQ(original::max(3, 3), std::max(3, 3)); + EXPECT_EQ(original::maximum(3, 3), std::max(3, 3)); } -// Tests for min +// Tests for minimum TEST(MathsTests, MinInt) { - EXPECT_EQ(original::min(3, 5), std::min(3, 5)); + EXPECT_EQ(original::minimum(3, 5), std::min(3, 5)); } TEST(MathsTests, MinDouble) { - EXPECT_EQ(original::min(3.5, 5.5), std::min(3.5, 5.5)); + EXPECT_EQ(original::minimum(3.5, 5.5), std::min(3.5, 5.5)); } TEST(MathsTests, MinEqual) { - EXPECT_EQ(original::min(3, 3), std::min(3, 3)); + EXPECT_EQ(original::minimum(3, 3), std::min(3, 3)); } // Tests for pow From 1d14a42ba655dfbc93dfdbeaff56baa552171a10 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:17:49 +0800 Subject: [PATCH 25/81] refactor: Rename to minimum --- src/core/bitSet.h | 2 +- src/core/maths.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/bitSet.h b/src/core/bitSet.h index ed1216a..1dd39fa 100644 --- a/src/core/bitSet.h +++ b/src/core/bitSet.h @@ -800,7 +800,7 @@ namespace std { } auto nb = bitSet(new_size); - const u_integer blocks_min = min(nb.map.size(), + const u_integer blocks_min = minimum(nb.map.size(), this->map.size()); for (u_integer i = 0; i < blocks_min; i++) { nb.map.set(i, this->map.get(i)); diff --git a/src/core/maths.h b/src/core/maths.h index 4f348b5..982b69c 100644 --- a/src/core/maths.h +++ b/src/core/maths.h @@ -100,7 +100,7 @@ TYPE maximum(TYPE a, TYPE b); * @endcode */ template -TYPE min(TYPE a, TYPE b); +TYPE minimum(TYPE a, TYPE b); /** * @brief Returns the result of raising a base to an exponent. @@ -192,7 +192,7 @@ auto original::maximum(TYPE a, TYPE b) -> TYPE } template -auto original::min(TYPE a, TYPE b) -> TYPE +auto original::minimum(TYPE a, TYPE b) -> TYPE { return a < b ? a : b; } From 759666fa1c061bb21e4a719ee6d03b86bfbe4614 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:27:22 +0800 Subject: [PATCH 26/81] refactor: Use parentheses to avoid symbol conflicts --- src/core/bitSet.h | 8 ++++---- src/core/blocksList.h | 8 ++++---- src/core/randomAccessIterator.h | 8 ++++---- src/core/sets.h | 4 ++-- src/core/skipList.h | 10 +++++----- src/core/stepIterator.h | 14 +++++++------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/core/bitSet.h b/src/core/bitSet.h index 1dd39fa..3cf4267 100644 --- a/src/core/bitSet.h +++ b/src/core/bitSet.h @@ -674,12 +674,12 @@ namespace std { auto* other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); if (this->container_ != other_it->container_) return this->container_ > other_it->container_ ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); return toOuterIdx(this->cur_block, this->cur_bit) - toOuterIdx(other_it->cur_block, other_it->cur_bit); } diff --git a/src/core/blocksList.h b/src/core/blocksList.h index 06ff3ce..d7aba84 100644 --- a/src/core/blocksList.h +++ b/src/core/blocksList.h @@ -742,12 +742,12 @@ namespace std { auto* other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); if (this->container_ != other_it->container_) return this->container_ > other_it->container_ ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); return static_cast(innerIdxToAbsIdx(this->cur_block, this->cur_pos)) - static_cast(innerIdxToAbsIdx(other_it->cur_block, other_it->cur_pos)); diff --git a/src/core/randomAccessIterator.h b/src/core/randomAccessIterator.h index fd7305a..3c79b60 100644 --- a/src/core/randomAccessIterator.h +++ b/src/core/randomAccessIterator.h @@ -260,12 +260,12 @@ namespace original { auto* other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); if (this->_container != other_it->_container) return this->_container > other_it->_container ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); return this->_ptr - other_it->_ptr; } diff --git a/src/core/sets.h b/src/core/sets.h index a9d0db9..7405ead 100644 --- a/src/core/sets.h +++ b/src/core/sets.h @@ -1653,8 +1653,8 @@ original::JSet::Iterator::operator-( auto other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); return skipListType::Iterator::operator-(*other_it); } diff --git a/src/core/skipList.h b/src/core/skipList.h index 08c5367..b105d24 100644 --- a/src/core/skipList.h +++ b/src/core/skipList.h @@ -517,12 +517,12 @@ template original::integer original::skipList::Iterator::operator-(const Iterator& other) const { if (const integer pos_dis = ptrDistance(&other, this); - pos_dis != std::numeric_limits::max()) return pos_dis; + pos_dis != (std::numeric_limits::max)()) return pos_dis; if (const integer neg_dis = ptrDistance(this, &other); - neg_dis != std::numeric_limits::max()) return -neg_dis; + neg_dis != (std::numeric_limits::max)()) return -neg_dis; return this->cur_ > other.cur_ ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); } template @@ -564,7 +564,7 @@ original::skipList::Iterator::ptrDistance(const s->next(); } if (e->isValid()){ - dis = std::numeric_limits::max(); + dis = (std::numeric_limits::max)(); } return dis; } diff --git a/src/core/stepIterator.h b/src/core/stepIterator.h index 8b037a8..2ab1079 100644 --- a/src/core/stepIterator.h +++ b/src/core/stepIterator.h @@ -199,7 +199,7 @@ namespace original s->next(); } if (e->isValid()){ - dis = std::numeric_limits::max(); + dis = (std::numeric_limits::max)(); } return dis; } @@ -302,15 +302,15 @@ namespace original auto* other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); if (const integer pos_dis = ptrDistance(other_it, this); - pos_dis != std::numeric_limits::max()) return pos_dis; + pos_dis != (std::numeric_limits::max)()) return pos_dis; if (const integer neg_dis = ptrDistance(this, other_it); - neg_dis != std::numeric_limits::max()) return -neg_dis; + neg_dis != (std::numeric_limits::max)()) return -neg_dis; return this->_ptr > other_it->_ptr ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); } template From 89f499928c3660b1b2b3d25cee28f17dff67dacc Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:29:47 +0800 Subject: [PATCH 27/81] refactor: Use cross-platform wrapper --- src/vibrant/async.h | 8 ++++---- src/vibrant/semaphores.h | 8 ++++---- src/vibrant/syncPoint.h | 4 ++-- src/vibrant/tasks.h | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vibrant/async.h b/src/vibrant/async.h index 5312a7c..9a7e67d 100644 --- a/src/vibrant/async.h +++ b/src/vibrant/async.h @@ -31,8 +31,8 @@ namespace original { class asyncWrapper { atomic ready_{makeAtomic(false)}; ///< Atomic flag indicating result readiness strongPtr result_; ///< Storage of asynchronous computation result - mutable pCondition cond_{}; ///< Condition variable for synchronization - mutable pMutex mutex_{}; ///< Mutex for thread safety + mutable condition cond_{}; ///< Condition variable for synchronization + mutable mutex mutex_{}; ///< Mutex for thread safety std::exception_ptr e_{}; ///< Exception pointer for error handling public: @@ -556,8 +556,8 @@ namespace original { class async::asyncWrapper { atomic ready_{makeAtomic(false)}; ///< Atomic flag indicating completion alternative result_; ///< Mark of asynchronous computation status - mutable pCondition cond_{}; ///< Condition variable for synchronization - mutable pMutex mutex_{}; ///< Mutex for thread safety + mutable condition cond_{}; ///< Condition variable for synchronization + mutable mutex mutex_{}; ///< Mutex for thread safety std::exception_ptr e_{}; ///< Exception pointer for error handling public: diff --git a/src/vibrant/semaphores.h b/src/vibrant/semaphores.h index 437bbd0..9488fef 100644 --- a/src/vibrant/semaphores.h +++ b/src/vibrant/semaphores.h @@ -47,8 +47,8 @@ namespace original { template class semaphore { u_integer count_; ///< Current semaphore count - pMutex mutex_; ///< Mutex for synchronization - pCondition condition_; ///< Condition variable for waiting + mutex mutex_; ///< Mutex for synchronization + condition condition_; ///< Condition variable for waiting public: /** @@ -128,8 +128,8 @@ namespace original { template<> class semaphore<0> { u_integer count_; ///< Current semaphore count (unbounded) - pMutex mutex_; ///< Mutex for synchronization - pCondition condition_; ///< Condition variable for waiting + mutex mutex_; ///< Mutex for synchronization + condition condition_; ///< Condition variable for waiting public: /** diff --git a/src/vibrant/syncPoint.h b/src/vibrant/syncPoint.h index fd1c616..4b17d04 100644 --- a/src/vibrant/syncPoint.h +++ b/src/vibrant/syncPoint.h @@ -25,8 +25,8 @@ namespace original { const u_integer max_arrived_; ///< Maximum number of threads required for synchronization u_integer arrived_; ///< Current number of arrived threads u_integer round_; ///< Current synchronization round - mutable pMutex mutex_; ///< Mutex for thread synchronization - mutable pCondition condition_; ///< Condition variable for thread waiting + mutable mutex mutex_; ///< Mutex for thread synchronization + mutable condition condition_; ///< Condition variable for thread waiting std::function complete_func_; ///< Completion function called by last thread std::exception_ptr e_; ///< Exception pointer for propagating completion function errors diff --git a/src/vibrant/tasks.h b/src/vibrant/tasks.h index 4e9a7b4..a35731d 100644 --- a/src/vibrant/tasks.h +++ b/src/vibrant/tasks.h @@ -172,8 +172,8 @@ namespace original { priorityTaskQueue tasks_waiting_; ///< Waiting tasks queue> task_immediate_; ///< Immediate tasks queue> tasks_deferred_; ///< Deferred tasks - mutable pCondition condition_; ///< Synchronization - mutable pMutex mutex_; ///< Mutex for thread safety + mutable condition condition_; ///< Synchronization + mutable mutex mutex_; ///< Mutex for thread safety bool stopped_; ///< Stop flag u_integer active_threads_; ///< Count of active threads u_integer idle_threads_; ///< Count of idle threads From 9139174996fb25559faca7e96664f90bb768fa6b Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:43:38 +0800 Subject: [PATCH 28/81] refactor: Add or remove keywords --- src/core/RBTree.h | 42 +++++++++++++++++++++--------------------- src/core/hashTable.h | 20 ++++++++++---------- src/vibrant/async.h | 6 +++--- src/vibrant/thread.h | 6 +++--- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/core/RBTree.h b/src/core/RBTree.h index 4e2d01b..8cc14eb 100644 --- a/src/core/RBTree.h +++ b/src/core/RBTree.h @@ -200,10 +200,10 @@ namespace original { static void connect(RBNode* parent, RBNode* child, bool is_left); }; - using color = typename RBNode::color; ///< Color type alias + using color = RBNode::color; ///< Color type alias static constexpr color BLACK = color::BLACK; ///< Black color constant static constexpr color RED = color::RED; ///< Red color constant - using rebind_alloc_node = typename ALLOC::template rebind_alloc; ///< Rebound allocator type + using rebind_alloc_node = ALLOC::template rebind_alloc; ///< Rebound allocator type RBNode* root_; ///< Root node pointer u_integer size_; ///< Number of elements @@ -476,7 +476,7 @@ original::RBTree::RBNode::RBNode(const RBNode &o } template -typename original::RBTree::RBNode& +original::RBTree::RBNode& original::RBTree::RBNode::operator=(const RBNode &other) { if (this == &other) return *this; @@ -539,38 +539,38 @@ void original::RBTree::RBNode::setValue(const V_ } template -typename original::RBTree::RBNode::color +original::RBTree::RBNode::color original::RBTree::RBNode::getColor() const { return this->color_; } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::RBNode::getPParent() const { return this->parent_; } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::RBNode::getPLeft() const { return this->left_; } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::RBNode::getPRight() const { return this->right_; } template -typename original::RBTree::RBNode*& +original::RBTree::RBNode*& original::RBTree::RBNode::getPLeftRef() { return this->left_; } template -typename original::RBTree::RBNode*& +original::RBTree::RBNode*& original::RBTree::RBNode::getPRightRef() { return this->right_; @@ -617,7 +617,7 @@ original::RBTree::Iterator::Iterator(const Itera } template -typename original::RBTree::Iterator& +original::RBTree::Iterator& original::RBTree::Iterator::operator=(const Iterator& other) { if (this == &other) @@ -704,7 +704,7 @@ bool original::RBTree::Iterator::isValid() const template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::treeCopy() const { if (!this->root_) { return nullptr; @@ -740,7 +740,7 @@ original::RBTree::treeCopy() const { } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::getPrecursorNode(RBNode *cur) const { if (!cur) return nullptr; @@ -762,7 +762,7 @@ original::RBTree::getPrecursorNode(RBNode *cur) } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::getSuccessorNode(RBNode *cur) const { if (!cur) return nullptr; @@ -784,7 +784,7 @@ original::RBTree::getSuccessorNode(RBNode *cur) } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::getMinNode() const { if (!root_) return nullptr; @@ -797,7 +797,7 @@ original::RBTree::getMinNode() const } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::getMaxNode() const { if (!this->root_) { @@ -812,7 +812,7 @@ original::RBTree::getMaxNode() const } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::replaceNode(RBNode* src, RBNode* tar) { auto moved_src = this->createNode(std::move(*src)); @@ -829,7 +829,7 @@ original::RBTree::replaceNode(RBNode* src, RBNod } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::createNode(const K_TYPE &key, const V_TYPE &value, color color, RBNode* parent, RBNode* left, RBNode* right) const { @@ -839,7 +839,7 @@ original::RBTree::createNode(const K_TYPE &key, } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::createNode(RBNode&& other_node) const { auto node = this->rebind_alloc.allocate(1); @@ -870,7 +870,7 @@ bool original::RBTree::highPriority(const K_TYPE } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::rotateLeft(RBNode *cur) { RBNode* child_left = cur; RBNode* child_root = child_left->getPRight(); @@ -884,7 +884,7 @@ original::RBTree::rotateLeft(RBNode *cur) { } template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::rotateRight(RBNode *cur) { RBNode* child_right = cur; RBNode* child_root = cur->getPLeft(); @@ -1117,7 +1117,7 @@ original::RBTree::RBTree(Compare compare) : root_(nullptr), size_(0), compare_(std::move(compare)) {} template -typename original::RBTree::RBNode* +original::RBTree::RBNode* original::RBTree::find(const K_TYPE &key) const { auto cur = this->root_; while (cur){ diff --git a/src/core/hashTable.h b/src/core/hashTable.h index 5b70e87..6035d27 100644 --- a/src/core/hashTable.h +++ b/src/core/hashTable.h @@ -165,13 +165,13 @@ namespace original { * @typedef rebind_alloc_node * @brief Rebound allocator type for node storage */ - using rebind_alloc_node = typename ALLOC::template rebind_alloc; + using rebind_alloc_node = ALLOC::template rebind_alloc; /** * @typedef rebind_alloc_pointer * @brief Rebound allocator type for pointer storage */ - using rebind_alloc_pointer = typename ALLOC::template rebind_alloc; + using rebind_alloc_pointer = ALLOC::template rebind_alloc; /** * @typedef buckets_type @@ -506,7 +506,7 @@ original::hashTable::hashNode::hashNode(const hashN } template -typename original::hashTable::hashNode& +original::hashTable::hashNode& original::hashTable::hashNode::operator=(const hashNode& other) { if (this == &other) return *this; @@ -553,13 +553,13 @@ void original::hashTable::hashNode::setValue(const } template -typename original::hashTable::hashNode* +original::hashTable::hashNode* original::hashTable::hashNode::getPPrev() const { throw unSupportedMethodError(); } template -typename original::hashTable::hashNode* +original::hashTable::hashNode* original::hashTable::hashNode::getPNext() const { return this->next_; } @@ -611,7 +611,7 @@ original::hashTable::Iterator::Iterator(const Itera } template -typename original::hashTable::Iterator& +original::hashTable::Iterator& original::hashTable::Iterator::operator=(const Iterator &other) { if (this == &other) return *this; @@ -689,7 +689,7 @@ bool original::hashTable::Iterator::isValid() const } template -typename original::hashTable::buckets_type +original::hashTable::buckets_type original::hashTable::bucketsCopy(const buckets_type& old_buckets) const { buckets_type new_buckets = buckets_type(old_buckets.size(), rebind_alloc_pointer{}, nullptr); @@ -714,7 +714,7 @@ original::hashTable::bucketsCopy(const buckets_type } template -typename original::hashTable::hashNode* +original::hashTable::hashNode* original::hashTable::createNode(const K_TYPE& key, const V_TYPE& value, hashNode* next) const { auto node = this->rebind_alloc.allocate(1); this->rebind_alloc.construct(node, key, value, next); @@ -740,7 +740,7 @@ original::hashTable::getBucketCount() const { } template -typename original::hashTable::hashNode* +original::hashTable::hashNode* original::hashTable::getBucket(const K_TYPE &key) const { u_integer code = this->getHashCode(key); return this->buckets[code]; @@ -812,7 +812,7 @@ original::hashTable::hashTable(HASH hash) } template -typename original::hashTable::hashNode* +original::hashTable::hashNode* original::hashTable::find(const K_TYPE& key) const { if (this->size_ == 0) return nullptr; diff --git a/src/vibrant/async.h b/src/vibrant/async.h index 9a7e67d..ae79a85 100644 --- a/src/vibrant/async.h +++ b/src/vibrant/async.h @@ -66,7 +66,7 @@ namespace original { * @param timeout Maximum time to wait * @return True if result is ready within timeout, false otherwise */ - bool waitFor(time::duration timeout) const; + [[nodiscard]] bool waitFor(time::duration timeout) const; /** * @brief Retrieves the result value (blocks until ready) @@ -86,7 +86,7 @@ namespace original { * @brief Gets a strong pointer to the result value * @return Strong pointer to the result */ - strongPtr getPtr() const; + [[nodiscard]] strongPtr getPtr() const; /** * @brief Throws stored exception if present @@ -590,7 +590,7 @@ namespace original { * @param timeout Maximum time to wait * @return True if result is ready within timeout, false otherwise */ - bool waitFor(const time::duration& timeout) const; + [[nodiscard]] bool waitFor(const time::duration& timeout) const; /** * @brief Waits for completion and checks for exceptions diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index a142430..b791e42 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -431,11 +431,11 @@ namespace original { */ [[nodiscard]] bool joinable() const override; - integer compareTo(const thread &other) const override; + [[nodiscard]] integer compareTo(const thread &other) const override; - u_integer toHash() const noexcept override; + [[nodiscard]] u_integer toHash() const noexcept override; - std::string className() const override; + [[nodiscard]] std::string className() const override; /** * @brief Wait for thread to complete From 8957956347f088b9cb8428c0e25659ceccaf3a8b Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:45:46 +0800 Subject: [PATCH 29/81] fix: Use atomicCastBack and atomicCastTo to ensure correct conversion --- src/vibrant/atomic.h | 78 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 2636758..71ceecc 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -319,6 +319,12 @@ namespace original { alignas(TYPE) volatile TYPE data_{}; + template + static To atomicCastTo(From value); + + template + static To atomicCastBack(From value); + atomicImpl(); explicit atomicImpl(TYPE value, memOrder order = SEQ_CST); @@ -597,6 +603,28 @@ constexpr bool original::isLockFreeType() noexcept { return sizeof(TYPE) == 4 || sizeof(TYPE) == 8; } +template +template +To original::atomicImpl::atomicCastTo(From value) +{ + if constexpr (std::is_pointer_v) { + return reinterpret_cast(value); + } else { + return static_cast(value); + } +} + +template +template +To original::atomicImpl::atomicCastBack(From value) +{ + if constexpr (std::is_pointer_v) { + return reinterpret_cast(value); + } else { + return static_cast(value); + } +} + template original::atomicImpl::atomicImpl() { @@ -630,9 +658,11 @@ void original::atomicImpl::store(TYPE value, const memOrder order) case memOrder::SEQ_CST: default: if constexpr (sizeof(TYPE) == 4) { - InterlockedExchange(reinterpret_cast(&this->data_), static_cast(value)); + InterlockedExchange(reinterpret_cast(&this->data_), + atomicCastTo(value)); } else { - InterlockedExchange64(reinterpret_cast(&this->data_), static_cast(value)); + InterlockedExchange64(reinterpret_cast(&this->data_), + atomicCastTo(value)); } break; } @@ -653,11 +683,15 @@ TYPE original::atomicImpl::load(const memOrder order) const noexcep case memOrder::SEQ_CST: default: if constexpr (sizeof(TYPE) == 4) { - value = InterlockedCompareExchange( - reinterpret_cast(&this->data_), 0, 0); + return atomicCastBack( + InterlockedCompareExchange( + reinterpret_cast(const_cast(&this->data_)), + 0, 0)); } else { - value = InterlockedCompareExchange64( - reinterpret_cast(&this->data_), 0, 0); + return atomicCastBack( + InterlockedCompareExchange64( + reinterpret_cast(const_cast(&this->data_)), + 0, 0)); } break; } @@ -689,9 +723,11 @@ original::atomicImpl& original::atomicImpl::operator+=(TYPE value) noexcept { if constexpr (sizeof(TYPE) == 4) { - InterlockedAdd(reinterpret_cast(&this->data_), static_cast(value)); + InterlockedAdd(reinterpret_cast(&this->data_), + atomicCastTo(value)); } else { - InterlockedAdd64(reinterpret_cast(&this->data_), static_cast(value)); + InterlockedAdd64(reinterpret_cast(&this->data_), + atomicCastTo(value)); } return *this; } @@ -707,9 +743,15 @@ template TYPE original::atomicImpl::exchange(TYPE value, memOrder) noexcept { if constexpr (sizeof(TYPE) == 4) { - return InterlockedExchange(reinterpret_cast(&this->data_), static_cast(value)); + return atomicCastBack( + InterlockedExchange(reinterpret_cast(&this->data_), + atomicCastTo(value)) + ); } else { - return InterlockedExchange64(reinterpret_cast(&this->data_), static_cast(value)); + return atomicCastBack( + InterlockedExchange64(reinterpret_cast(&this->data_), + atomicCastTo(value)) + ); } } @@ -719,18 +761,18 @@ bool original::atomicImpl::exchangeCmp(TYPE& expected, TYPE desired if constexpr (sizeof(TYPE) == 4) { val_type old = InterlockedCompareExchange( reinterpret_cast(&this->data_), - static_cast(desired), - static_cast(expected)); - const bool success = old == static_cast(expected); - if (!success) expected = static_cast(old); + atomicCastTo(desired), + atomicCastTo(expected)); + const bool success = old == atomicCastTo(expected); + if (!success) expected = atomicCastBack(old); return success; } else { val_type old = InterlockedCompareExchange64( reinterpret_cast(&this->data_), - static_cast(desired), - static_cast(expected)); - const bool success = old == static_cast(expected); - if (!success) expected = static_cast(old); + atomicCastTo(desired), + atomicCastTo(expected)); + const bool success = old == atomicCastTo(expected); + if (!success) expected = atomicCastBack(old); return success; } } From 7bb11241fa742e7cb39e8f9ec237638f0e015e24 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:46:03 +0800 Subject: [PATCH 30/81] fix: Correct function signature --- src/vibrant/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index 71ceecc..ce8bf75 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -406,9 +406,9 @@ namespace original { atomicImpl& operator-=(TYPE value) noexcept; - TYPE exchange(TYPE value, memOrder order = SEQ_CST) noexcept; + TYPE exchange(const TYPE& value, memOrder order = SEQ_CST) noexcept; - bool exchangeCmp(TYPE& expected, TYPE desired, memOrder order = SEQ_CST) noexcept; + bool exchangeCmp(TYPE& expected, const TYPE& desired, memOrder order = SEQ_CST) noexcept; ~atomicImpl() = default; From 53c432e03ebbe5a2303b4b605ba1808a029ec62f Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:49:02 +0800 Subject: [PATCH 31/81] fix: Fix headers containing order --- src/vibrant/condition.h | 3 --- src/vibrant/mutex.h | 6 +++--- src/vibrant/thread.h | 4 ++-- src/vibrant/zeit.h | 8 ++++++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index c4944bf..789156d 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -4,9 +4,6 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC -#define WIN32_LEAN_AND_MEAN -#include -#include #endif #include "mutex.h" diff --git a/src/vibrant/mutex.h b/src/vibrant/mutex.h index 4cb2465..56b136b 100644 --- a/src/vibrant/mutex.h +++ b/src/vibrant/mutex.h @@ -1,16 +1,16 @@ #ifndef MUTEX_H #define MUTEX_H +#include "config.h" + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" #elif ORIGINAL_COMPILER_MSVC -#define WIN32_LEAN_AND_MEAN -#include -#include #endif #include "error.h" #include "tuple.h" +#include "zeit.h" #include /** diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index b791e42..e1842bd 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -4,9 +4,9 @@ #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" #elif ORIGINAL_COMPILER_MSVC +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN -#include -#include +#endif #endif #include "error.h" diff --git a/src/vibrant/zeit.h b/src/vibrant/zeit.h index 2289c68..226b6b7 100644 --- a/src/vibrant/zeit.h +++ b/src/vibrant/zeit.h @@ -1,15 +1,19 @@ #ifndef ORIGINAL_ZEIT_H #define ORIGINAL_ZEIT_H +#include "config.h" + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN -#include +#endif +#include +#include #endif #include -#include "config.h" #include "comparable.h" #include "hash.h" #include "printable.h" From 35785ff892adc2ea30d468246348cbb014095c06 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:51:01 +0800 Subject: [PATCH 32/81] fix: Use full namespace --- src/vibrant/zeit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vibrant/zeit.h b/src/vibrant/zeit.h index 226b6b7..3ce6b39 100644 --- a/src/vibrant/zeit.h +++ b/src/vibrant/zeit.h @@ -843,7 +843,7 @@ namespace original { * @warning When converting back to time::point, the time point will only * have second-level precision (sub-second components will be zero) */ - explicit operator point() const; + explicit operator original::time::point() const; point toPoint() const; @@ -1773,7 +1773,7 @@ original::time::UTCTime::value(const calendar calendar) const { } } -inline original::time::UTCTime::operator point() const { +inline original::time::UTCTime::operator original::time::point() const { time_val_type total_days = 0; for (integer year = EPOCH_YEAR; year < this->year_; ++year) { From 51ed749d16f02b0a2d20988916de674512eb94f0 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:51:24 +0800 Subject: [PATCH 33/81] feat: Impl time::point::now for msvc --- src/vibrant/zeit.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/vibrant/zeit.h b/src/vibrant/zeit.h index 3ce6b39..5f70aee 100644 --- a/src/vibrant/zeit.h +++ b/src/vibrant/zeit.h @@ -1394,9 +1394,20 @@ original::time::point::now() { time_val_type ns = tv.tv_sec * FACTOR_SECOND + tv.tv_usec * FACTOR_MICROSECOND; return point(ns, NANOSECOND); #elif ORIGINAL_COMPILER_MSVC - // Other implements not complete - return point(); + FILETIME file_time; + GetSystemTimePreciseAsFileTime(&file_time); + + ULARGE_INTEGER uli; + uli.LowPart = file_time.dwLowDateTime; + uli.HighPart = file_time.dwHighDateTime; + + constexpr time_val_type WINDOWS_TO_UNIX_EPOCH = 11644473600LL * FACTOR_SECOND; + + const time_val_type nanoseconds = uli.QuadPart * 100 - WINDOWS_TO_UNIX_EPOCH; + + return point{nanoseconds, NANOSECOND}; #endif + return point{}; } inline original::time::point::point(const time_val_type val, const unit unit) From 3836ccbcec657ec2a890854408766fdaef7c5d1a Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:52:31 +0800 Subject: [PATCH 34/81] feat: Add cross-platform wrapper for mutex.h and condition.h --- src/vibrant/condition.h | 45 ++++++++++++++++++++++++++++++ src/vibrant/mutex.h | 61 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index 789156d..bca399f 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -205,6 +205,29 @@ namespace original ~wCondition() override; }; #endif + + class condition final : public conditionBase { + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + pCondition cond_; + #elif ORIGINAL_COMPILER_MSVC + wCondition cond_; + #endif + + public: + using conditionBase::wait; + using conditionBase::waitFor; + + condition(); + + void wait(mutexBase& mutex) override; + + bool waitFor(mutexBase& mutex, time::duration d) override; + + void notify() override; + + void notifyAll() override; + }; + } template void original::conditionBase::wait(mutexBase& mutex, Pred predicate) noexcept(noexcept(predicate())) { @@ -347,4 +370,26 @@ inline void original::wCondition::notifyAll() } #endif +inline original::condition::condition() = default; + +inline void original::condition::wait(mutexBase& mutex) +{ + this->cond_.wait(mutex); +} + +inline bool original::condition::waitFor(mutexBase& mutex, time::duration d) +{ + return this->cond_.waitFor(mutex, d); +} + +inline void original::condition::notify() +{ + this->cond_.notify(); +} + +inline void original::condition::notifyAll() +{ + this->cond_.notifyAll(); +} + #endif //CONDITION_H diff --git a/src/vibrant/mutex.h b/src/vibrant/mutex.h index 56b136b..68f7c8d 100644 --- a/src/vibrant/mutex.h +++ b/src/vibrant/mutex.h @@ -238,6 +238,38 @@ namespace original { }; #endif + class mutex final : public mutexBase { + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + pMutex mutex_; + #elif ORIGINAL_COMPILER_MSVC + wMutex mutex_; + #endif + + public: + using native_handle = + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + pMutex::native_handle; + #elif ORIGINAL_COMPILER_MSVC + wMutex::native_handle; + #endif + + mutex(); + + mutex(mutex&&) = delete; + + mutex& operator=(mutex&) = delete; + + [[nodiscard]] ul_integer id() const override; + + [[nodiscard]] void* nativeHandle() noexcept override; + + void lock() override; + + bool tryLock() override; + + void unlock() override; + }; + /** * @class uniqueLock * @brief RAII wrapper for single mutex locking @@ -471,7 +503,34 @@ inline original::wMutex::~wMutex() } #endif -inline original::uniqueLock::uniqueLock(mutexBase& mutex, lockPolicy policy) +inline original::mutex::mutex() = default; + +inline original::ul_integer original::mutex::id() const +{ + return this->mutex_.id(); +} + +inline void* original::mutex::nativeHandle() noexcept +{ + return this->mutex_.nativeHandle(); +} + +inline void original::mutex::lock() +{ + this->mutex_.lock(); +} + +inline bool original::mutex::tryLock() +{ + return this->mutex_.tryLock(); +} + +inline void original::mutex::unlock() +{ + this->mutex_.unlock(); +} + +inline original::uniqueLock::uniqueLock(mutexBase& mutex, const lockPolicy policy) : mutex_(mutex), is_locked(false) { switch (policy) { case MANUAL_LOCK: From ee7b93a4049816f413e04a26c65d564b3fdf6317 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:54:01 +0800 Subject: [PATCH 35/81] fix: Align feature of wMutex to pMutex --- src/vibrant/condition.h | 24 +++++++++--------------- src/vibrant/mutex.h | 24 +++++++++++------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index bca399f..b9c303a 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -329,31 +329,23 @@ inline original::wCondition::wCondition() : cond_{} inline void original::wCondition::wait(mutexBase& mutex) { - const auto w_mutex = dynamic_cast(&mutex); - if (!w_mutex) { - throw valueError("Invalid mutex type for condition variable: must be wMutex"); - } - if (const auto handle = static_cast(w_mutex->nativeHandle()); - !SleepConditionVariableCS(&this->cond_, handle, INFINITE)) { - throw sysError("Failed to wait on condition variable (SleepConditionVariableCS returned error " + + if (const auto handle = static_cast(mutex.nativeHandle()); + !SleepConditionVariableSRW(&this->cond_, handle, INFINITE, 0)) { + throw sysError("Failed to wait on condition variable (SleepConditionVariableSRW returned error " + printable::formatString(GetLastError())); } } inline bool original::wCondition::waitFor(mutexBase& mutex, const time::duration d) { - const auto w_mutex = dynamic_cast(&mutex); - if (!w_mutex) { - throw valueError("Invalid mutex type for condition variable: must be wMutex"); - } - - const auto handle = static_cast(w_mutex->nativeHandle()); - if (const auto timeout_ms = d.toDWMilliseconds(); !SleepConditionVariableCS(&this->cond_, handle, timeout_ms)) { + const auto handle = static_cast(mutex.nativeHandle()); + if (const auto timeout_ms = d.toDWMilliseconds(); + !SleepConditionVariableSRW(&this->cond_, handle, timeout_ms, 0)) { const DWORD error = GetLastError(); if (error == ERROR_TIMEOUT) { return false; } - throw sysError("Failed to timed wait on condition variable (SleepConditionVariableCS returned error " + + throw sysError("Failed to timed wait on condition variable (SleepConditionVariableSRW returned error " + printable::formatString(error)); } return true; @@ -368,6 +360,8 @@ inline void original::wCondition::notifyAll() { WakeAllConditionVariable(&this->cond_); } + +inline original::wCondition::~wCondition() = default; #endif inline original::condition::condition() = default; diff --git a/src/vibrant/mutex.h b/src/vibrant/mutex.h index 68f7c8d..c7306f9 100644 --- a/src/vibrant/mutex.h +++ b/src/vibrant/mutex.h @@ -214,9 +214,9 @@ namespace original { }; #elif ORIGINAL_COMPILER_MSVC class wMutex final : public mutexBase { - CRITICAL_SECTION cs_; + SRWLOCK lock_; public: - using native_handle = CRITICAL_SECTION; + using native_handle = SRWLOCK; explicit wMutex(); @@ -467,40 +467,38 @@ inline original::pMutex::~pMutex() { } } #elif ORIGINAL_COMPILER_MSVC -inline original::wMutex::wMutex() : cs_{} +inline original::wMutex::wMutex() { - InitializeCriticalSection(&this->cs_); + InitializeSRWLock(&this->lock_); } inline original::ul_integer original::wMutex::id() const { - return reinterpret_cast(&this->cs_); + return reinterpret_cast(&this->lock_); } inline void* original::wMutex::nativeHandle() noexcept { - return &this->cs_; + return &this->lock_; } inline void original::wMutex::lock() { - EnterCriticalSection(&this->cs_); + AcquireSRWLockExclusive(&this->lock_); } inline bool original::wMutex::tryLock() { - return TryEnterCriticalSection(&this->cs_) != 0; + return TryAcquireSRWLockExclusive(&this->lock_) != 0; } inline void original::wMutex::unlock() { - LeaveCriticalSection(&this->cs_); + ReleaseSRWLockExclusive(&this->lock_); } -inline original::wMutex::~wMutex() -{ - DeleteCriticalSection(&this->cs_); -} +inline original::wMutex::~wMutex() = default; + #endif inline original::mutex::mutex() = default; From d747e40d104bcfbda8e1e08ce0b5b06e7b7ec364 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:56:55 +0800 Subject: [PATCH 36/81] fix: Fix access control permission issues --- src/core/RBTree.h | 2 +- src/core/filterStream.h | 11 ++++++----- src/core/hashTable.h | 3 +-- src/core/skipList.h | 2 +- src/vibrant/coroutines.h | 16 ++++++++-------- src/vibrant/tasks.h | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/core/RBTree.h b/src/core/RBTree.h index 8cc14eb..dcef898 100644 --- a/src/core/RBTree.h +++ b/src/core/RBTree.h @@ -38,7 +38,7 @@ namespace original { typename ALLOC = allocator, typename Compare = increaseComparator> class RBTree { - protected: + public: /** * @class RBNode diff --git a/src/core/filterStream.h b/src/core/filterStream.h index b903183..0705e2e 100644 --- a/src/core/filterStream.h +++ b/src/core/filterStream.h @@ -26,14 +26,15 @@ namespace original{ template class filterStream { - ///< Null filter instance used as operator placeholder in stream processing - static const strongPtr> nullFilter; - + public: /// @internal Operator types for postfix conversion enum class opts{AND = 1, OR = 0, NOT = 2, LEFT_BRACKET = 3, RIGHT_BRACKET = 4}; + private: + ///< Null filter instance used as operator placeholder in stream processing + static const strongPtr> nullFilter; - mutable chain>> stream; ///< Filter operand chain - mutable chain ops; ///< Operator sequence storage + mutable chain>> stream{}; ///< Filter operand chain + mutable chain ops{}; ///< Operator sequence storage mutable bool flag; ///< Postfix conversion status flag protected: diff --git a/src/core/hashTable.h b/src/core/hashTable.h index 6035d27..e9f891e 100644 --- a/src/core/hashTable.h +++ b/src/core/hashTable.h @@ -4,7 +4,6 @@ #include "allocator.h" #include "couple.h" #include "hash.h" -#include "singleDirectionIterator.h" #include "vector.h" #include "wrapper.h" @@ -53,7 +52,7 @@ namespace original { */ template, typename HASH = hash> class hashTable{ - protected: + public: /** * @class hashNode diff --git a/src/core/skipList.h b/src/core/skipList.h index b105d24..d62a663 100644 --- a/src/core/skipList.h +++ b/src/core/skipList.h @@ -43,7 +43,7 @@ namespace original { typename ALLOC = allocator, typename Compare = increaseComparator> class skipList { - protected: + public: /** * @class skipListNode * @brief Internal node class for Skip List diff --git a/src/vibrant/coroutines.h b/src/vibrant/coroutines.h index ed28af6..108d302 100644 --- a/src/vibrant/coroutines.h +++ b/src/vibrant/coroutines.h @@ -55,6 +55,14 @@ namespace original { */ template class generator { + public: + struct promise_type; + private: + using handle = std::coroutine_handle; ///< Coroutine handle type + + handle handle_; ///< Underlying coroutine handle + + public: /** * @struct promise_type * @brief Implements the coroutine promise interface for generator @@ -168,14 +176,6 @@ namespace original { bool operator==(const iterator& other) const; }; - using handle = std::coroutine_handle; ///< Coroutine handle type - - handle handle_; ///< Underlying coroutine handle - - public: - using promise_type = promise_type; ///< Promise type for coroutine protocol - using iterator = iterator; ///< Iterator type for range operations - generator(const generator&) = delete; ///< Copy constructor deleted generator& operator=(const generator&) = delete; ///< Copy assignment deleted diff --git a/src/vibrant/tasks.h b/src/vibrant/tasks.h index a35731d..588fdc0 100644 --- a/src/vibrant/tasks.h +++ b/src/vibrant/tasks.h @@ -47,6 +47,7 @@ namespace original { * manually activated or discarded on shutdown. */ class taskDelegator { + public: // ==================== Task Base Interface ==================== /** @@ -111,7 +112,6 @@ namespace original { async::future getFuture(); }; - public: // ==================== Task Priorities ==================== /** From 937cc0b3712a5fcee99bd3c89969fbe80a1c1cc7 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:57:52 +0800 Subject: [PATCH 37/81] fix: Fix template mismatch issue --- src/vibrant/generators.h | 119 ++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 63 deletions(-) diff --git a/src/vibrant/generators.h b/src/vibrant/generators.h index f07bd81..14bd26a 100644 --- a/src/vibrant/generators.h +++ b/src/vibrant/generators.h @@ -3,6 +3,7 @@ #include "coroutines.h" #include "couple.h" #include "sets.h" +#include "vector.h" namespace original { @@ -26,45 +27,6 @@ namespace original { template coroutine::generator> enumerate(coroutine::generator gen); - /** - * @brief Collects generator elements into a set. - * @tparam TYPE The type of elements in the generator. - * @tparam SET The set type to collect into (default: hashSet). - * @param gen The generator to collect from. - * @return A set containing all unique elements from the generator. - * @details Transforms a generator sequence into a set container, removing duplicates - * and providing fast lookup capabilities. - * - * Example: - * @code - * auto vec = vector{1, 2, 2, 3, 3, 3}; - * auto gen = vec.generator(); - * auto set = collect(gen); // {1, 2, 3} - * @endcode - */ - template> - requires ExtendsOf>>, SET> - SET collect(coroutine::generator gen); - - /** - * @brief Collects generator elements into a list container. - * @tparam TYPE The type of elements in the generator. - * @tparam SERIAL The list container type (default: vector). - * @param gen The generator to collect from. - * @return A list container with all generator elements in order. - * @details Converts a generator sequence into a concrete list container, - * preserving element order and allowing random access. - * - * Example: - * @code - * auto gen = someContainer.generator(); - * auto vec = list(gen); // Creates vector with all elements - * @endcode - */ - template typename SERIAL = vector> - requires ExtendsOf>, SERIAL> - SERIAL list(coroutine::generator gen); - /** * @brief Transforms generator elements using a callable. * @tparam TYPE The input element type. @@ -644,42 +606,73 @@ namespace original { */ template auto find(F&& f); -} -template -original::coroutine::generator> -original::enumerate(coroutine::generator gen) -{ - u_integer i = 0; - for (auto elem : gen) + /** + * @brief Collects generator elements into a set. + * @tparam TYPE The type of elements in the generator. + * @tparam SET The set type to collect into (default: hashSet). + * @param gen The generator to collect from. + * @return A set containing all unique elements from the generator. + * @details Transforms a generator sequence into a set container, removing duplicates + * and providing fast lookup capabilities. + * + * Example: + * @code + * auto vec = vector{1, 2, 2, 3, 3, 3}; + * auto gen = vec.generator(); + * auto set = collect(gen); // {1, 2, 3} + * @endcode + */ + template> + requires original::ExtendsOf>>, SET> + SET collect(coroutine::generator gen) { - co_yield {i, elem}; - i += 1; + SET set; + for (auto elem : gen) + { + set.add(elem); + } + return set; } -} -template -requires original::ExtendsOf>>, SET> -SET original::collect(coroutine::generator gen) -{ - SET set; - for (auto elem : gen) + /** + * @brief Collects generator elements into a list container. + * @tparam TYPE The type of elements in the generator. + * @tparam SERIAL The list container type (default: vector). + * @param gen The generator to collect from. + * @return A list container with all generator elements in order. + * @details Converts a generator sequence into a concrete list container, + * preserving element order and allowing random access. + * + * Example: + * @code + * auto gen = someContainer.generator(); + * auto vec = list(gen); // Creates vector with all elements + * @endcode + */ + template typename SERIAL = vector> + requires original::ExtendsOf>, SERIAL> + SERIAL list(coroutine::generator gen) { - set.add(elem); + SERIAL list; + for (auto elem : gen) + { + list.pushEnd(elem); + } + return list; } - return set; } -template class SERIAL> -requires original::ExtendsOf>, SERIAL> -SERIAL original::list(coroutine::generator gen) +template +original::coroutine::generator> +original::enumerate(coroutine::generator gen) { - SERIAL list; + u_integer i = 0; for (auto elem : gen) { - list.pushEnd(elem); + co_yield {i, elem}; + i += 1; } - return list; } template From 32c28f9c7bbe74ff7ccca0ae39aae5b77a5b0b0f Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 19:58:55 +0800 Subject: [PATCH 38/81] refactor: Change destructors to virtual function --- src/core/RBTree.h | 2 +- src/core/hashTable.h | 2 +- src/core/skipList.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/RBTree.h b/src/core/RBTree.h index dcef898..713f737 100644 --- a/src/core/RBTree.h +++ b/src/core/RBTree.h @@ -460,7 +460,7 @@ namespace original { * @brief Destructor * @details Cleans up all tree nodes and allocated memory */ - ~RBTree(); + virtual ~RBTree(); }; } diff --git a/src/core/hashTable.h b/src/core/hashTable.h index e9f891e..e9bc169 100644 --- a/src/core/hashTable.h +++ b/src/core/hashTable.h @@ -491,7 +491,7 @@ namespace original { * @brief Destroys hashTable * @details Cleans up all nodes and buckets */ - ~hashTable(); + virtual ~hashTable(); }; } diff --git a/src/core/skipList.h b/src/core/skipList.h index d62a663..bbf9a71 100644 --- a/src/core/skipList.h +++ b/src/core/skipList.h @@ -366,7 +366,7 @@ namespace original { * @brief Destructor * @details Cleans up all list nodes and allocated memory */ - ~skipList(); + virtual ~skipList(); }; } From 5947cec881a076931ffe3b693fcc4f2403040ec5 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:04:17 +0800 Subject: [PATCH 39/81] fix: Fix headers containing order --- src/vibrant/thread.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index e1842bd..5540348 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -1,6 +1,8 @@ #ifndef THREAD_H #define THREAD_H +#include "config.h" + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include "pthread.h" #elif ORIGINAL_COMPILER_MSVC @@ -11,6 +13,7 @@ #include "error.h" #include "functional" +#include "hash.h" #include "ownerPtr.h" #include "zeit.h" From 5fb9a82f721df6c71138727abc0acf123118ac60 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:05:06 +0800 Subject: [PATCH 40/81] fix: Fix API and logic of wThread --- src/vibrant/thread.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/vibrant/thread.h b/src/vibrant/thread.h index 5540348..e0cb3a6 100644 --- a/src/vibrant/thread.h +++ b/src/vibrant/thread.h @@ -252,7 +252,7 @@ namespace original { explicit wThread(); template - explicit wThread(Callback c, ARGS&& args...); + explicit wThread(Callback c, ARGS&&... args...); wThread(wThread&& other) noexcept; @@ -628,7 +628,7 @@ inline bool original::wThread::valid() const inline original::wThread::wThread() : handle(), is_joinable() {} template -original::wThread::wThread(Callback c, ARGS&& args, ...) : handle(), is_joinable(true) +original::wThread::wThread(Callback c, ARGS&&... args, ...) : handle(), is_joinable(true) { auto bound_lambda = [func = std::forward(c), ...lambda_args = std::forward(args)]() mutable { @@ -640,7 +640,16 @@ original::wThread::wThread(Callback c, ARGS&& args, ...) : handle(), is_joinable auto task = new bound_thread_data(std::move(bound_lambda)); - this->handle = CreateThread(nullptr, 0, task, nullptr, 0, nullptr); + static auto threadEntry = [](LPVOID param) -> DWORD { + bound_thread_data::run(param); + return 0; + }; + + this->handle = CreateThread(nullptr, 0, threadEntry, task, 0, nullptr); + if (this->handle == nullptr) { + delete task; + throw sysError("Failed to create thread (CreateThread returned null)"); + } } inline original::wThread::wThread(wThread&& other) noexcept : wThread() @@ -697,11 +706,15 @@ inline std::string original::wThread::className() const inline void original::wThread::join() { WaitForSingleObject(this->handle, INFINITE); + this->is_joinable = false; + this->handle = {}; } inline void original::wThread::detach() { CloseHandle(this->handle); + this->is_joinable = false; + this->handle = {}; } inline original::wThread::~wThread() @@ -756,7 +769,7 @@ inline void original::thread::sleep(const time::duration& d) ", errno: " + std::to_string(errno) + ")"); } #elif ORIGINAL_COMPILER_MSVC - Sleep(static_cast((d.value() + time::FACTOR_MILLISECOND - 1) / time::FACTOR_MILLISECOND)); + Sleep(d.toDWMilliseconds()); #endif } From 2ac0072f4ba1bd4824a3b4a40973519530d8afb4 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:05:59 +0800 Subject: [PATCH 41/81] refactor: Rename to null --- src/core/optional.h | 110 ++++++++++++++++++++++---------------------- src/core/types.h | 12 ++--- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/core/optional.h b/src/core/optional.h index 9726891..f86036c 100644 --- a/src/core/optional.h +++ b/src/core/optional.h @@ -8,7 +8,7 @@ * @file optional.h * @brief Type-safe optional value container * @details Provides an alternative class that can either contain a value of type 'TYPE' - * or be in an empty state (represented by original::none from types.h). This implementation + * or be in an empty state (represented by original::null from types.h). This implementation * provides: * - Value semantics with proper construction/destruction * - Safe access operations with error checking @@ -20,7 +20,7 @@ * Key features: * - Type-safe alternative to raw pointers for optional values * - No dynamic memory allocation (uses union storage) - * - Explicit empty state handling with original::none + * - Explicit empty state handling with original::null * - Exception-safe operations * - STL-compatible interface */ @@ -33,7 +33,7 @@ namespace original { * @tparam TYPE The type of value to store * @details This class provides a way to represent optional values without * using pointers. It can either contain a value of type TYPE or be empty. - * The empty state is represented using original::none from types.h. + * The empty state is represented using original::null from types.h. * * The implementation uses a union for storage to avoid dynamic allocation * and ensure optimal performance. All operations provide strong exception @@ -62,18 +62,18 @@ namespace original { class alternative { /** * @union storage - * @brief Internal storage for either TYPE or none - * @details Uses a union to store either the value type or none, + * @brief Internal storage for either TYPE or null + * @details Uses a union to store either the value type or null, * with proper construction/destruction handling. The union ensures * that only one member is active at any time, managed by the - * non_none_type_ flag. + * non_null_type_ flag. */ union storage { TYPE type_; ///< Storage for the contained value - none none_; ///< Storage for empty state (from types.h) + null null_; ///< Storage for empty state (from types.h) /** - * @brief Default constructor (initializes to none) + * @brief Default constructor (initializes to null) */ storage() noexcept; @@ -87,14 +87,14 @@ namespace original { ~storage(); }; - bool non_none_type_; ///< Flag indicating whether value is present (true = TYPE, false = none) + bool non_null_type_; ///< Flag indicating whether value is present (true = TYPE, false = null) storage val_; ///< The actual storage union /** * @brief Safely destroys the current contents * @note Properly calls destructor based on current state - * @details If non_none_type_ is true, calls TYPE destructor, - * otherwise calls none destructor. Ensures RAII compliance. + * @details If non_null_type_ is true, calls TYPE destructor, + * otherwise calls null destructor. Ensures RAII compliance. */ void destroy() noexcept; @@ -286,11 +286,11 @@ namespace original { explicit alternative(); /** - * @brief Constructs from none (empty state) - * @param n none value indicating empty state + * @brief Constructs from null (empty state) + * @param n null value indicating empty state * @post hasValue() == false */ - explicit alternative(none n); + explicit alternative(null n); /** * @brief Constructs with value present @@ -331,19 +331,19 @@ namespace original { alternative& operator=(std::in_place_t t) noexcept; /** - * @brief Assignment from none to reset to empty state - * @param n none value indicating empty state + * @brief Assignment from null to reset to empty state + * @param n null value indicating empty state * @return Reference to this alternative * @post hasValue() == false * @details Resets the alternative to the empty state. This operation * is equivalent to calling reset() but provides a more expressive syntax - * when working with none values. The assignment clears the "present" state + * when working with null values. The assignment clears the "present" state * and ensures the alternative is empty. * * Example usage: * @code * alternative flag(std::in_place); // Present state - * flag = original::none; // Now empty + * flag = original::null; // Now empty * * if (!flag) { * // This will execute since flag is now empty @@ -352,14 +352,14 @@ namespace original { * // In generic code: * template * void clearAlternative(alternative& opt) { - * opt = original::none; // Works for both alternative and alternative + * opt = original::null; // Works for both alternative and alternative * } * @endcode * * @note This operation is noexcept and always succeeds. * @see reset() */ - alternative& operator=(none n) noexcept; + alternative& operator=(null n) noexcept; /** * @brief Resets to empty state @@ -422,7 +422,7 @@ namespace std { template original::alternative::storage::storage() noexcept { - new(&this->none_) none{}; + new(&this->null_) null; } template @@ -430,33 +430,33 @@ original::alternative::storage::~storage() {} template void original::alternative::destroy() noexcept { - if (this->non_none_type_){ + if (this->non_null_type_){ this->val_.type_.~TYPE(); - this->non_none_type_ = false; + this->non_null_type_ = false; } else { - this->val_.none_.~none(); - this->non_none_type_ = true; + this->val_.null_.~null(); + this->non_null_type_ = true; } } template original::alternative::alternative() - : non_none_type_(false), val_() {} + : non_null_type_(false), val_() {} template template original::alternative::alternative(Args &&... args) - : non_none_type_(true), val_() { + : non_null_type_(true), val_() { new (&this->val_.type_) TYPE{ std::forward(args)... }; } template original::alternative::alternative(const alternative& other) { - this->non_none_type_ = other.non_none_type_; - if (other.non_none_type_) { + this->non_null_type_ = other.non_null_type_; + if (other.non_null_type_) { new (&val_.type_) TYPE{ other.val_.type_ }; } else { - new (&val_.none_) none{}; + new (&val_.null_) null; } } @@ -467,22 +467,22 @@ original::alternative::operator=(const alternative& other) { return *this; this->destroy(); - this->non_none_type_ = other.non_none_type_; - if (other.non_none_type_) { + this->non_null_type_ = other.non_null_type_; + if (other.non_null_type_) { new (&val_.type_) TYPE{ other.val_.type_ }; } else { - new (&val_.none_) none{}; + new (&val_.null_) null; } return *this; } template original::alternative::alternative(alternative&& other) noexcept { - this->non_none_type_ = other.non_none_type_; - if (this->non_none_type_){ + this->non_null_type_ = other.non_null_type_; + if (this->non_null_type_){ new (&val_.type_) TYPE{ std::move(other.val_.type_) }; } else{ - new (&val_.none_) none{}; + new (&val_.null_) null; } } @@ -493,11 +493,11 @@ original::alternative::operator=(alternative&& other) noexcept { return *this; this->destroy(); - this->non_none_type_ = other.non_none_type_; - if (this->non_none_type_){ + this->non_null_type_ = other.non_null_type_; + if (this->non_null_type_){ new (&val_.type_) TYPE{ std::move(other.val_.type_) }; } else{ - new (&val_.none_) none{}; + new (&val_.null_) null; } return *this; } @@ -508,15 +508,15 @@ void original::alternative::swap(alternative& other) noexcept if (this == &other) return; - std::swap(this->non_none_type_, other.non_none_type_); + std::swap(this->non_null_type_, other.non_null_type_); std::swap(this->val_, other.val_); } template const TYPE& original::alternative::operator*() const { - if (!this->non_none_type_) - throw valueError("Dereferencing a original::none value"); + if (!this->non_null_type_) + throw valueError("Dereferencing a original::null value"); return this->val_.type_; } @@ -524,8 +524,8 @@ original::alternative::operator*() const { template TYPE& original::alternative::operator*() { - if (!this->non_none_type_) - throw valueError("Dereferencing a original::none value"); + if (!this->non_null_type_) + throw valueError("Dereferencing a original::null value"); return this->val_.type_; } @@ -533,8 +533,8 @@ original::alternative::operator*() { template const TYPE* original::alternative::operator->() const { - if (!this->non_none_type_) - throw valueError("Accessing member of a original::none value"); + if (!this->non_null_type_) + throw valueError("Accessing member of a original::null value"); return &this->val_.type_; } @@ -542,20 +542,20 @@ original::alternative::operator->() const { template TYPE* original::alternative::operator->() { - if (!this->non_none_type_) - throw valueError("Accessing member of a original::none value"); + if (!this->non_null_type_) + throw valueError("Accessing member of a original::null value"); return &this->val_.type_; } template const TYPE* original::alternative::get() const { - return this->non_none_type_ ? &this->val_.type_ : nullptr; + return this->non_null_type_ ? &this->val_.type_ : nullptr; } template TYPE* original::alternative::get() { - return this->non_none_type_ ? &this->val_.type_ : nullptr; + return this->non_null_type_ ? &this->val_.type_ : nullptr; } template @@ -567,14 +567,14 @@ template template void original::alternative::emplace(Args &&... args) { this->destroy(); - this->non_none_type_ = true; + this->non_null_type_ = true; new (&val_.type_) TYPE{ std::forward(args)... }; } template void original::alternative::set(const TYPE &t) { this->destroy(); - this->non_none_type_ = true; + this->non_null_type_ = true; new (&val_.type_) TYPE{ t }; } @@ -588,7 +588,7 @@ original::alternative::operator=(const TYPE& t) template original::alternative::operator bool() const { - return this->non_none_type_; + return this->non_null_type_; } template @@ -604,7 +604,7 @@ original::alternative::~alternative() { inline original::alternative::alternative() = default; -inline original::alternative::alternative(none) {} +inline original::alternative::alternative(null) {} inline original::alternative::alternative(std::in_place_t) : has_value_(true) {} @@ -621,7 +621,7 @@ original::alternative::operator=(std::in_place_t) noexcept } inline original::alternative& -original::alternative::operator=(none) noexcept +original::alternative::operator=(null) noexcept { this->reset(); return *this; diff --git a/src/core/types.h b/src/core/types.h index e3228cd..b3717dd 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -24,19 +24,19 @@ namespace original { // ==================== Fundamental Types ==================== /** - * @class none + * @class null * @brief A placeholder type representing the absence of a value. * @details This class provides consteval operations and can be converted to bool, * always returning false. Useful for template metaprogramming and * representing empty states. */ - class none { + class null { public: /// @brief Default constructor (consteval) - consteval explicit none() = default; + consteval explicit null() = default; /// @brief Default destructor (constexpr) - constexpr ~none() = default; + constexpr ~null() = default; /** * @brief Bool conversion operator @@ -662,11 +662,11 @@ namespace original { } // namespace original -consteval original::none::operator bool() const { +consteval original::null::operator bool() const { return false; } -consteval bool original::none::operator!() const { +consteval bool original::null::operator!() const { return true; } From acb84817e070d36a41cc77d7197cf4081e9a15a8 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:07:10 +0800 Subject: [PATCH 42/81] fix: Fix initialization order --- src/core/maps.h | 7 +++---- src/core/sets.h | 8 ++++---- src/core/skipList.h | 5 ++++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/core/maps.h b/src/core/maps.h index 33ba211..59862b3 100644 --- a/src/core/maps.h +++ b/src/core/maps.h @@ -830,8 +830,8 @@ namespace original { typename V_TYPE, typename Compare = increaseComparator, typename ALLOC = allocator>> - class JMap final : public skipList, - public map, + class JMap final : public map, + public skipList, public iterable>, public printable { @@ -1993,8 +1993,7 @@ bool original::JMap::Iterator::isValid() const { template original::JMap::JMap(Compare comp, ALLOC alloc) - : skipListType(std::move(comp)) , - map(std::move(alloc)) {} + : map(std::move(alloc)), skipListType(std::move(comp)) {} template original::JMap::JMap(const JMap& other) : JMap() { diff --git a/src/core/sets.h b/src/core/sets.h index 7405ead..9c784fd 100644 --- a/src/core/sets.h +++ b/src/core/sets.h @@ -708,8 +708,8 @@ namespace original { template , typename ALLOC = allocator>> - class JSet final : public skipList, - public set, + class JSet final : public set, + public skipList, public iterable, public printable { using skipListType = skipList; @@ -1723,8 +1723,8 @@ bool original::JSet::Iterator::isValid() const { template original::JSet::JSet(Compare comp, ALLOC alloc) - : skipListType(std::move(comp)), - set(std::move(alloc)) {} + : set(std::move(alloc)), + skipListType(std::move(comp)) {} template original::JSet::JSet(const JSet& other) : JSet() { diff --git a/src/core/skipList.h b/src/core/skipList.h index bbf9a71..96fa80d 100644 --- a/src/core/skipList.h +++ b/src/core/skipList.h @@ -672,7 +672,10 @@ original::skipList::findLastNode() const { template original::skipList::skipList(Compare compare) - : size_(0), head_(this->createNode()), compare_(std::move(compare)) {} + : size_(0), head_(nullptr), compare_(std::move(compare)) +{ + this->head_ = this->createNode(); +} template original::skipList::skipListNode* From 3ac85086b9d32837096b0373e7c0285b3f5a6755 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:07:27 +0800 Subject: [PATCH 43/81] refactor: Use parentheses to avoid symbol conflicts --- src/core/maps.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/maps.h b/src/core/maps.h index 59862b3..c06034c 100644 --- a/src/core/maps.h +++ b/src/core/maps.h @@ -1923,8 +1923,8 @@ original::JMap::Iterator::operator-( auto other_it = dynamic_cast(&other); if (other_it == nullptr) return this > &other ? - std::numeric_limits::max() : - std::numeric_limits::min(); + (std::numeric_limits::max)() : + (std::numeric_limits::min)(); return skipListType::Iterator::operator-(*other_it); } From 84c348a95a5168bafdf3690602485d7c1f6da58b Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:07:42 +0800 Subject: [PATCH 44/81] refactor: Use std::rethrow_exception --- src/vibrant/syncPoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vibrant/syncPoint.h b/src/vibrant/syncPoint.h index 4b17d04..bb3b2a1 100644 --- a/src/vibrant/syncPoint.h +++ b/src/vibrant/syncPoint.h @@ -111,7 +111,7 @@ inline void original::syncPoint::arrive() { lock.unlock(); this->condition_.notifyAll(); if (this->e_) { - throw this->e_; + std::rethrow_exception(this->e_); } } } From 7bcd081d1b7237a4bf126532049179d16f8e527a Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:08:41 +0800 Subject: [PATCH 45/81] fix: Fix comparison logic --- test/other/test3.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/other/test3.cpp b/test/other/test3.cpp index 158705d..b7c24fa 100644 --- a/test/other/test3.cpp +++ b/test/other/test3.cpp @@ -8,7 +8,6 @@ #include "chain.h" #include "vector.h" #include "algorithms.h" -#include "filter.h" int main(){ @@ -148,7 +147,7 @@ int main(){ std::cout << "p1 == p2: " << original::printable::formatString(p1 == p2) << std::endl; std::cout << "p1 < p2: " << original::printable::formatString(p1 < p2) << std::endl; auto cmp = p1 <=> p2; - std::cout << (cmp == nullptr) << std::endl; + std::cout << (cmp == 0) << std::endl; std::cout << "p1: " << p1 << std::endl; while (!p1.empty()) { From f3bbf696a5878d1929d47d23ef3775018d3f20db Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:10:42 +0800 Subject: [PATCH 46/81] fix: Use cross-platform wrapper --- test/other/test6.cpp | 35 +++++-------- .../unit_test/test_vibrant/test_condition.cpp | 52 +++++++++---------- test/unit_test/test_vibrant/test_mutex.cpp | 50 +++++++++--------- test/unit_test/test_vibrant/test_thread.cpp | 30 +++++++---- 4 files changed, 82 insertions(+), 85 deletions(-) diff --git a/test/other/test6.cpp b/test/other/test6.cpp index 75b5743..a2619e6 100644 --- a/test/other/test6.cpp +++ b/test/other/test6.cpp @@ -1,6 +1,8 @@ #include #include "atomic.h" +#include "array.h" +#include "allocator.h" #include "thread.h" #include "maps.h" #include "mutex.h" @@ -15,37 +17,24 @@ using namespace original::literals; int main() { std::cout << "id of main thread: " << original::thread::thisId() << std::endl; - original::pMutex print_mtx; - original::pCondition p; - - auto printErr = [&](const original::error& e){ - original::uniqueLock lock{print_mtx}; - std::cout << e << ": " << e.message() << std::endl; - p.notify(); - }; - - const auto err = original::valueError("Divided by zero"); - original::thread print_thread {printErr, std::cref(err)}; - p.wait(print_mtx); - - original::pMutex mutex; + original::mutex mutex; auto task1 = [&](const int a, const std::string& b) { original::uniqueLock lock{mutex}; std::cout << b << a << std::endl; }; - original::pThread t1{task1, 1, "show: "}; + original::thread t1{task1, 1, "show: "}; original::thread::sleep(100_ms); std::cout << "id t1: " << t1.id() << std::endl; t1.join(); - original::pThread t2{task1, 2, "show: "}; + original::thread t2{task1, 2, "show: "}; t2.join(); - original::pThread t3{task1, 3, "show: "}; + original::thread t3{task1, 3, "show: "}; auto t4 = std::move(t3); t4.join(); - original::pThread t5{task1, 4, "show: "}; - original::pThread t6{task1, 5, "show: "}; + original::thread t5{task1, 4, "show: "}; + original::thread t6{task1, 5, "show: "}; if (t5) { std::cout << "t5 is valid" << std::endl; } @@ -58,11 +47,11 @@ int main() original::thread t7{task1, 6, "show: "}; original::thread t8{task1, 7, "show: "}; - original::pThread t9{task1, 8, "show: "}; + original::thread t9{task1, 8, "show: "}; original::thread t10{std::move(t9), original::thread::AUTO_JOIN}; original::thread::sleep(100_ms); std::cout << "t10 id: " << t10.id() << std::endl; - original::pThread t11{task1, 9, "show: "}; + original::thread t11{task1, 9, "show: "}; original::thread t12{std::move(t11)}; original::thread t13; @@ -94,8 +83,8 @@ int main() std::cout << "On win64: " << original::printable::formatString(original::ON_WIN64()) << std::endl; std::cout << "Using GCC: " << original::printable::formatString(original::USING_GCC()) << std::endl; - original::pMutex m1; - original::pMutex m2; + original::mutex m1; + original::mutex m2; original::multiLock ml{m1, m2}; auto d1 = original::time::duration(100, original::time::MILLISECOND); diff --git a/test/unit_test/test_vibrant/test_condition.cpp b/test/unit_test/test_vibrant/test_condition.cpp index d5081bf..0618ebc 100644 --- a/test/unit_test/test_vibrant/test_condition.cpp +++ b/test/unit_test/test_vibrant/test_condition.cpp @@ -11,8 +11,8 @@ using namespace original::literals; class pConditionTest : public testing::Test { protected: - pMutex mutex; - pCondition cond; + mutex mutex_; + condition cond_; bool ready = false; }; @@ -20,27 +20,27 @@ class ProducerConsumerTest : public testing::Test { protected: queue buffer; static constexpr std::size_t MAX_SIZE = 5; - pMutex mutex; - pCondition cond_full; // 消费者等待“非空” - pCondition cond_empty; // 生产者等待“非满” + mutex mutex_; + condition cond_full; // 消费者等待“非空” + condition cond_empty; // 生产者等待“非满” bool done = false; }; // 基本通知机制:等待一个条件,然后 notify 唤醒 TEST_F(pConditionTest, BasicNotifyTest) { thread t([&] { - uniqueLock lock(mutex); + uniqueLock lock(mutex_); while (!ready) { - cond.wait(mutex); + cond_.wait(mutex_); } }, thread::AUTO_JOIN); thread::sleep(50_ms); // 让线程进入 wait 状态 { - uniqueLock lock(mutex); + uniqueLock lock(mutex_); ready = true; - cond.notify(); + cond_.notify(); } t.join(); @@ -49,8 +49,8 @@ TEST_F(pConditionTest, BasicNotifyTest) { // 测试 waitFor 的超时行为 TEST_F(pConditionTest, TimedWaitTimeoutTest) { - uniqueLock lock(mutex); - const bool result = cond.waitFor(mutex, 200_ms); + uniqueLock lock(mutex_); + const bool result = cond_.waitFor(mutex_, 200_ms); EXPECT_FALSE(result); // 应超时 } @@ -58,15 +58,15 @@ TEST_F(pConditionTest, TimedWaitTimeoutTest) { TEST_F(pConditionTest, TimedWaitNotTimeoutTest) { thread t([&] { thread::sleep(50_ms); // 等待 50ms 再唤醒 - uniqueLock lock(mutex); + uniqueLock lock(mutex_); ready = true; - cond.notify(); + cond_.notify(); }, thread::AUTO_JOIN); bool result; { - uniqueLock lock(mutex); - result = cond.waitFor(mutex, 200_ms); + uniqueLock lock(mutex_); + result = cond_.waitFor(mutex_, 200_ms); } EXPECT_TRUE(result); @@ -78,23 +78,23 @@ TEST_F(pConditionTest, NotifyAllWakesAllWaiters) { ready = false; thread t1([&] { - uniqueLock lock(mutex); - while (!ready) cond.wait(mutex); + uniqueLock lock(mutex_); + while (!ready) cond_.wait(mutex_); wake_count++; }); thread t2([&] { - uniqueLock lock(mutex); - while (!ready) cond.wait(mutex); + uniqueLock lock(mutex_); + while (!ready) cond_.wait(mutex_); wake_count++; }); thread::sleep(50_ms); // 等待线程进入阻塞状态 { - uniqueLock lock(mutex); + uniqueLock lock(mutex_); ready = true; - cond.notifyAll(); + cond_.notifyAll(); } t1.join(); @@ -110,8 +110,8 @@ TEST_F(ProducerConsumerTest, ProducerConsumerWorkCorrectly) { // 消费者线程 thread consumer([&] { while (true) { - uniqueLock lock(mutex); - cond_full.wait(mutex, [&]{ + uniqueLock lock(mutex_); + cond_full.wait(mutex_, [&]{ return !buffer.empty() || done; }); if (done && buffer.empty()) @@ -129,8 +129,8 @@ TEST_F(ProducerConsumerTest, ProducerConsumerWorkCorrectly) { // 生产者线程 thread producer([&] { for (int i = 1; i <= total_count; ++i) { - uniqueLock lock(mutex); - cond_empty.wait(mutex, [&] { + uniqueLock lock(mutex_); + cond_empty.wait(mutex_, [&] { return buffer.size() < MAX_SIZE; }); buffer.push(i); // 生产 @@ -139,7 +139,7 @@ TEST_F(ProducerConsumerTest, ProducerConsumerWorkCorrectly) { // 设置完成标志并广播 { - uniqueLock lock(mutex); + uniqueLock lock(mutex_); done = true; cond_full.notifyAll(); } diff --git a/test/unit_test/test_vibrant/test_mutex.cpp b/test/unit_test/test_vibrant/test_mutex.cpp index 721acea..7337a85 100644 --- a/test/unit_test/test_vibrant/test_mutex.cpp +++ b/test/unit_test/test_vibrant/test_mutex.cpp @@ -6,19 +6,19 @@ using namespace original; TEST(MutexTest, LockUnlockDoesNotThrow) { - pMutex m; + mutex m; EXPECT_NO_THROW(m.lock()); EXPECT_NO_THROW(m.unlock()); } TEST(MutexTest, TryLockSuccess) { - pMutex m; + mutex m; EXPECT_NO_THROW(m.tryLock()); EXPECT_NO_THROW(m.unlock()); } TEST(MutexTest, TryLockContested) { - pMutex m; + mutex m; std::thread t( [&m] { @@ -39,7 +39,7 @@ TEST(MutexTest, PreventsDataRaceWithMultipleThreads) { constexpr int thread_count = 10; constexpr int iterations = 10000; int counter = 0; - pMutex m; + mutex m; auto increment = [&] { @@ -64,7 +64,7 @@ TEST(MutexTest, PreventsDataRaceWithMultipleThreads) { TEST(MutexTest, LockInConstructorAndUnlockInDestructor) { { - pMutex pm; + mutex pm; const uniqueLock m(pm); // 默认锁定 EXPECT_TRUE(m.isLocked()); } @@ -73,7 +73,7 @@ TEST(MutexTest, LockInConstructorAndUnlockInDestructor) { TEST(MutexTest, TryLockConstructor) { { - pMutex pm; + mutex pm; const uniqueLock m(pm, uniqueLock::TRY_LOCK); // 使用 tryLock EXPECT_TRUE(m.isLocked()); } @@ -81,22 +81,22 @@ TEST(MutexTest, TryLockConstructor) { } TEST(MutexTest, MutexIsNonCopyable) { - EXPECT_FALSE(std::is_copy_constructible_v); - EXPECT_FALSE(std::is_copy_assignable_v); + EXPECT_FALSE(std::is_copy_constructible_v); + EXPECT_FALSE(std::is_copy_assignable_v); EXPECT_FALSE(std::is_copy_constructible_v); EXPECT_FALSE(std::is_copy_assignable_v); } TEST(MutexTest, MutexIsNonMovable) { - EXPECT_FALSE(std::is_move_constructible_v); - EXPECT_FALSE(std::is_move_assignable_v); + EXPECT_FALSE(std::is_move_constructible_v); + EXPECT_FALSE(std::is_move_assignable_v); EXPECT_FALSE(std::is_move_constructible_v); EXPECT_FALSE(std::is_move_assignable_v); } // TryLock失败时,uniqueLock::isLocked() 应为 false TEST(MutexTest, TryLockFailsIsLockedFalse) { - pMutex pm; + mutex pm; pm.lock(); // 主线程先锁住 const uniqueLock s(pm, uniqueLock::TRY_LOCK); // 尝试获取失败 @@ -107,7 +107,7 @@ TEST(MutexTest, TryLockFailsIsLockedFalse) { // scopeLock析构后,mutex可以再次上锁 TEST(MutexTest, RAIIUnlocksCorrectly) { - pMutex pm; + mutex pm; { uniqueLock s(pm); EXPECT_TRUE(s.isLocked()); @@ -124,7 +124,7 @@ TEST(MutexTest, UniqueLockProtectsCriticalSection) { constexpr int thread_count = 10; constexpr int iterations = 10000; int counter = 0; - pMutex m; + mutex m; auto increment = [&] { @@ -148,7 +148,7 @@ TEST(MutexTest, UniqueLockProtectsCriticalSection) { // TryLock获取失败时不会 unlock TEST(MutexTest, TryLockFailDoesNotUnlock) { - pMutex pm; + mutex pm; pm.lock(); { @@ -162,7 +162,7 @@ TEST(MutexTest, TryLockFailDoesNotUnlock) { // TryLock获取成功后,锁应被释放 TEST(MutexTest, TryLockSuccessUnlocksOnDestruction) { - pMutex pm; + mutex pm; { if (const uniqueLock s(pm, uniqueLock::TRY_LOCK); s.isLocked()) { SUCCEED(); // 成功加锁 @@ -176,7 +176,7 @@ TEST(MutexTest, TryLockSuccessUnlocksOnDestruction) { // 测试解锁后可以再次加锁 TEST(MutexTest, CanRelockAfterUnlock) { - pMutex m; + mutex m; m.lock(); m.unlock(); EXPECT_NO_THROW(m.lock()); // 再次加锁不应抛出异常 @@ -185,7 +185,7 @@ TEST(MutexTest, CanRelockAfterUnlock) { // 测试uniqueLock解锁后可以再次加锁 TEST(MutexTest, UniqueLockCanRelockAfterUnlock) { - pMutex pm; + mutex pm; { uniqueLock lock(pm); lock.unlock(); @@ -198,7 +198,7 @@ TEST(MutexTest, UniqueLockCanRelockAfterUnlock) { // 测试多次加锁解锁循环 TEST(MutexTest, MultipleLockUnlockCycles) { - pMutex m; + mutex m; for (int i = 0; i < 100; ++i) { EXPECT_NO_THROW(m.lock()); EXPECT_NO_THROW(m.unlock()); @@ -207,7 +207,7 @@ TEST(MutexTest, MultipleLockUnlockCycles) { // 测试uniqueLock手动锁策略 TEST(MutexTest, ManualLockPolicy) { - pMutex pm; + mutex pm; { uniqueLock lock(pm, uniqueLock::MANUAL_LOCK); EXPECT_FALSE(lock.isLocked()); @@ -223,7 +223,7 @@ TEST(MutexTest, ManualLockPolicy) { // 测试跨线程的加锁解锁顺序 TEST(MutexTest, CrossThreadLockUnlockSequence) { - pMutex m; + mutex m; std::atomic thread_locked{false}; std::atomic main_proceed{false}; @@ -251,7 +251,7 @@ TEST(MultiLockTest, MultiLockLocksAndUnlocksInReverseOrder) { std::vector unlock_order; class Trackable { - pMutex mutex_; + mutex mutex_; std::vector& lock_record_; std::vector& unlock_record_; public: @@ -299,7 +299,7 @@ TEST(MultiLockTest, MultiLockLocksAndUnlocksInReverseOrder) { TEST(MultiLockTest, MultiLockProtectsMultipleResources) { constexpr int iterations = 1000; int x = 0, y = 0; - pMutex mx, my; + mutex mx, my; auto worker = [&]() { for (int i = 0; i < iterations; ++i) { @@ -319,7 +319,7 @@ TEST(MultiLockTest, MultiLockProtectsMultipleResources) { } TEST(MutexTest, AdoptLockPolicyAssumesLocked) { - pMutex m; + mutex m; m.lock(); // 手动加锁 { @@ -334,7 +334,7 @@ TEST(MutexTest, AdoptLockPolicyAssumesLocked) { } TEST(MultiLockTest, AdoptLockSkipsLocking) { - pMutex m1, m2; + mutex m1, m2; m1.lock(); m2.lock(); @@ -352,7 +352,7 @@ TEST(MultiLockTest, AdoptLockSkipsLocking) { } TEST(MultiLockTest, TryLockFailsWhenAnyMutexUnavailable) { - pMutex m1, m2; + mutex m1, m2; m1.lock(); // 抢占一个锁 const multiLock lock(lockGuard::TRY_LOCK, m1, m2); diff --git a/test/unit_test/test_vibrant/test_thread.cpp b/test/unit_test/test_vibrant/test_thread.cpp index 7bcfdca..d206311 100644 --- a/test/unit_test/test_vibrant/test_thread.cpp +++ b/test/unit_test/test_vibrant/test_thread.cpp @@ -9,6 +9,12 @@ using namespace original::literals; using namespace std::literals; namespace { + using thread_type = +#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG + pThread; +#elif ORIGINAL_COMPILER_MSVC + wThread; +#endif // Test class with member functions class Worker { public: @@ -274,13 +280,13 @@ TEST_F(ThreadTest, ThreadIdAfterMove) { ASSERT_EQ(t2.id(), 0); // After joining, ID should be 0 } -// Test pThread ID functionality -TEST_F(ThreadTest, PThreadId) { - pThread pt([] {}); +// Test platform thread ID functionality +TEST_F(ThreadTest, PlatformThreadId) { + thread_type pt([] {}); const ul_integer id1 = pt.id(); ASSERT_NE(id1, 0); - pThread pt2(std::move(pt)); + thread_type pt2(std::move(pt)); ASSERT_EQ(pt2.id(), id1); // ID should be preserved after move ASSERT_EQ(pt.id(), 0); // Moved-from pThread should have ID 0 @@ -467,21 +473,23 @@ TEST_F(ThreadTest, PrintableInterface) { t2.join(); } -// Test pThread printable interface -TEST_F(ThreadTest, PThreadPrintableInterface) { - pThread pt1([] {}); - pThread pt2; +// Test platform thread printable interface +TEST_F(ThreadTest, PlatformThreadPrintableInterface) { + thread_type pt1([] {}); + thread_type pt2; + + const std::string platform_thread_name = ON_WINDOWS() ? "wThread": "pThread"; // Test className - ASSERT_EQ(pt1.className(), "pThread"); + ASSERT_EQ(pt1.className(), platform_thread_name); // Test toString const std::string str1 = pt1.toString(false); const std::string str2 = pt2.toString(false); - ASSERT_TRUE(str1.find("pThread") != std::string::npos); + ASSERT_TRUE(str1.find(platform_thread_name) != std::string::npos); ASSERT_TRUE(str1.find(std::to_string(pt1.id())) != std::string::npos); - ASSERT_TRUE(str2.find("pThread") != std::string::npos); + ASSERT_TRUE(str2.find(platform_thread_name) != std::string::npos); pt1.join(); } \ No newline at end of file From 427bd2acf2393a9c7fda38285a98e27532c4b2b9 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:11:31 +0800 Subject: [PATCH 47/81] fix: Fix test assertion statements --- test/unit_test/test_core/test_printable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit_test/test_core/test_printable.cpp b/test/unit_test/test_core/test_printable.cpp index 053b16b..c3dd95e 100644 --- a/test/unit_test/test_core/test_printable.cpp +++ b/test/unit_test/test_core/test_printable.cpp @@ -26,7 +26,7 @@ TEST(PrintableTest, ToStringTest) { // 测试 toString 传入 false,不带换行 std::string str = obj.toString(false); EXPECT_TRUE(str.find("TestClass") != std::string::npos); // 应该包含类名 - EXPECT_TRUE(str.find("0x") != std::string::npos); // 应该包含地址信息 + EXPECT_TRUE(str.find('@') != std::string::npos); // 应该包含地址信息 // 测试 toString 传入 true,带换行 str = obj.toString(true); @@ -88,5 +88,5 @@ TEST(PrintableTest, OutputOperatorTest) { std::ostringstream oss; oss << obj; EXPECT_TRUE(oss.str().find("TestClass") != std::string::npos); // 输出应包含类名 - EXPECT_TRUE(oss.str().find("0x") != std::string::npos); // 输出应包含对象地址 + EXPECT_TRUE(oss.str().find('@') != std::string::npos); // 输出应包含对象地址 } From 71a9eee1467c295d3255655a9e88d94bd1647d0d Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:12:40 +0800 Subject: [PATCH 48/81] refactor: Add qualifiers --- test/unit_test/test_core/test_printable.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit_test/test_core/test_printable.cpp b/test/unit_test/test_core/test_printable.cpp index c3dd95e..e49e535 100644 --- a/test/unit_test/test_core/test_printable.cpp +++ b/test/unit_test/test_core/test_printable.cpp @@ -3,7 +3,7 @@ namespace original { // 创建一个继承 printable 的测试类 - class TestClass : public printable { + class TestClass final : public printable { public: std::string className() const override { return "TestClass"; @@ -21,7 +21,7 @@ TEST(PrintableTest, ClassNameTest) { // 测试 toString() 方法 TEST(PrintableTest, ToStringTest) { - original::TestClass obj; + const original::TestClass obj; // 测试 toString 传入 false,不带换行 std::string str = obj.toString(false); @@ -35,7 +35,7 @@ TEST(PrintableTest, ToStringTest) { // 测试 toCString() 方法 TEST(PrintableTest, ToCStringTest) { - original::TestClass obj; + const original::TestClass obj; const char* c_str = obj.toCString(false); EXPECT_TRUE(std::string(c_str).find("TestClass") != std::string::npos); } @@ -84,7 +84,7 @@ TEST(PrintableTest, FormatEnumTest) { // 测试输出操作符 TEST(PrintableTest, OutputOperatorTest) { - original::TestClass obj; + const original::TestClass obj; std::ostringstream oss; oss << obj; EXPECT_TRUE(oss.str().find("TestClass") != std::string::npos); // 输出应包含类名 From c69c9a4cbc10908a2a462bbf412dc449a1f1ec92 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:13:12 +0800 Subject: [PATCH 49/81] fix: Add missing header --- test/unit_test/test_core/test_algorithms.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit_test/test_core/test_algorithms.cpp b/test/unit_test/test_core/test_algorithms.cpp index 17b2542..376fd91 100644 --- a/test/unit_test/test_core/test_algorithms.cpp +++ b/test/unit_test/test_core/test_algorithms.cpp @@ -1,5 +1,6 @@ #include #include // std algorithm +#include #include "array.h" #include "vector.h" #include "algorithms.h" // original algorithm From 6cfb3cc8e915a056daf90dfe1daa46da0d5038ee Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:14:13 +0800 Subject: [PATCH 50/81] fix: Fix the definition method of callable objects --- test/unit_test/test_core/test_JMap.cpp | 16 ++++++++++------ test/unit_test/test_core/test_JSet.cpp | 18 +++++++++++------- test/unit_test/test_core/test_hashMap.cpp | 10 +++++++--- test/unit_test/test_core/test_hashSet.cpp | 10 +++++++--- test/unit_test/test_core/test_treeMap.cpp | 10 +++++++--- test/unit_test/test_core/test_treeSet.cpp | 10 +++++++--- 6 files changed, 49 insertions(+), 25 deletions(-) diff --git a/test/unit_test/test_core/test_JMap.cpp b/test/unit_test/test_core/test_JMap.cpp index 78051c3..c59f4b3 100644 --- a/test/unit_test/test_core/test_JMap.cpp +++ b/test/unit_test/test_core/test_JMap.cpp @@ -23,6 +23,15 @@ class JMapTest : public testing::Test { JMap* stringMap{}; }; +namespace { + template + struct CustomCompare { + bool operator()(const int a, const int b) const { + return a > b; // Reverse order + } + }; +} + // Basic Functionality Tests TEST_F(JMapTest, InitialState) { EXPECT_EQ(intMap->size(), 0); @@ -209,13 +218,8 @@ EXPECT_EQ(intMap->size(), 0); // NOLINT(bugprone-use-after-move) // Custom Comparator Test TEST(JMapCustomCompareTest, CustomCompareFunction) { -struct CustomCompare { - bool operator()(const int a, const int b) const { - return a > b; // Reverse order - } -}; -JMap customMap; +JMap> customMap; customMap.add(1, 10); customMap.add(2, 20); customMap.add(3, 30); diff --git a/test/unit_test/test_core/test_JSet.cpp b/test/unit_test/test_core/test_JSet.cpp index ea04800..d5e3e83 100644 --- a/test/unit_test/test_core/test_JSet.cpp +++ b/test/unit_test/test_core/test_JSet.cpp @@ -22,6 +22,16 @@ class JSetTest : public testing::Test { JSet* stringSet{}; }; +namespace +{ + template + struct ReverseCompare { + bool operator()(int a, int b) const { + return a > b; + } + }; +} + // 基础功能测试 TEST_F(JSetTest, InitialState) { EXPECT_EQ(intSet->size(), 0); @@ -139,13 +149,7 @@ TEST_F(JSetTest, ToString) { // 自定义比较器测试(反向排序) TEST(JSetCustomCompareTest, CustomCompare) { - struct ReverseCompare { - bool operator()(int a, int b) const { - return a > b; - } - }; - - JSet set; + JSet> set; for (int i = 1; i <= 3; ++i) set.add(i); auto it = set.begins(); diff --git a/test/unit_test/test_core/test_hashMap.cpp b/test/unit_test/test_core/test_hashMap.cpp index c51c23b..b7b9192 100644 --- a/test/unit_test/test_core/test_hashMap.cpp +++ b/test/unit_test/test_core/test_hashMap.cpp @@ -232,15 +232,19 @@ TEST_F(HashMapTest, ToString) { EXPECT_TRUE(str.find("20") != std::string::npos); } -// Custom Hash Function Test -TEST(HashMapCustomHashTest, CustomHashFunction) { +namespace +{ + template struct CustomHash { u_integer operator()(const int key) const { return key % 10; // Simple hash for testing } }; +} - hashMap customMap; +// Custom Hash Function Test +TEST(HashMapCustomHashTest, CustomHashFunction) { + hashMap> customMap; for (int i = 0; i < 20; ++i) { customMap.add(i, i * 10); } diff --git a/test/unit_test/test_core/test_hashSet.cpp b/test/unit_test/test_core/test_hashSet.cpp index 0a061d5..50106f2 100644 --- a/test/unit_test/test_core/test_hashSet.cpp +++ b/test/unit_test/test_core/test_hashSet.cpp @@ -188,15 +188,19 @@ TEST_F(HashSetTest, ToString) { EXPECT_TRUE(str.find('2') != std::string::npos); } -// Custom Hash Function Test -TEST(HashSetCustomHashTest, CustomHashFunction) { +namespace +{ + template struct CustomHash { u_integer operator()(const int key) const { return key % 10; // Simple hash for testing } }; +} - hashSet customSet; +// Custom Hash Function Test +TEST(HashSetCustomHashTest, CustomHashFunction) { + hashSet> customSet; for (int i = 0; i < 20; ++i) { customSet.add(i); } diff --git a/test/unit_test/test_core/test_treeMap.cpp b/test/unit_test/test_core/test_treeMap.cpp index c2a2758..02df525 100644 --- a/test/unit_test/test_core/test_treeMap.cpp +++ b/test/unit_test/test_core/test_treeMap.cpp @@ -230,15 +230,19 @@ TEST_F(TreeMapTest, MoveAssignment) { EXPECT_EQ(intMap->size(), 0); // NOLINT(bugprone-use-after-move) } -// Custom Comparator Test -TEST(TreeMapCustomCompareTest, CustomCompareFunction) { +namespace +{ + template struct CustomCompare { bool operator()(const int a, const int b) const { return a > b; // Reverse order } }; +} - treeMap customMap; +// Custom Comparator Test +TEST(TreeMapCustomCompareTest, CustomCompareFunction) { + treeMap> customMap; customMap.add(1, 10); customMap.add(2, 20); customMap.add(3, 30); diff --git a/test/unit_test/test_core/test_treeSet.cpp b/test/unit_test/test_core/test_treeSet.cpp index 8f40582..ed57f2f 100644 --- a/test/unit_test/test_core/test_treeSet.cpp +++ b/test/unit_test/test_core/test_treeSet.cpp @@ -187,15 +187,19 @@ TEST_F(TreeSetTest, MoveAssignment) { EXPECT_EQ(intSet->size(), 0); // NOLINT(bugprone-use-after-move) } -// Custom Comparator Test -TEST(TreeSetCustomCompareTest, CustomCompareFunction) { +namespace +{ + template struct CustomCompare { bool operator()(const int a, const int b) const { return a > b; // Reverse order } }; +} - treeSet customSet; +// Custom Comparator Test +TEST(TreeSetCustomCompareTest, CustomCompareFunction) { + treeSet> customSet; customSet.add(1); customSet.add(2); customSet.add(3); From 45e56d14528977caa37447511865cd14305b51b3 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee Date: Fri, 10 Oct 2025 20:14:34 +0800 Subject: [PATCH 51/81] fix: Fix the test logic of SharedFutureVoidWaitFor --- test/unit_test/test_vibrant/test_async.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/unit_test/test_vibrant/test_async.cpp b/test/unit_test/test_vibrant/test_async.cpp index 9072cba..1906e2b 100644 --- a/test/unit_test/test_vibrant/test_async.cpp +++ b/test/unit_test/test_vibrant/test_async.cpp @@ -894,19 +894,26 @@ TEST(AsyncTest, SharedFutureWaitFor) { // 测试 sharedFuture 的 waitFor 方法 TEST(AsyncTest, SharedFutureVoidWaitFor) { - std::atomic executed{false}; + auto executed = std::make_shared>(false); - const auto sf = async::get([&executed] { + const auto sf = async::get([executed] { thread::sleep(milliseconds(100)); - executed = true; + executed->store(true); }).share(); // 等待足够长的时间 const bool success = sf.waitFor(milliseconds(150)); EXPECT_TRUE(success); EXPECT_TRUE(sf.ready()); - EXPECT_NO_THROW(sf.result()); - EXPECT_TRUE(executed); + + // 在检查result之前确保任务已完成 + if (sf.ready()) { + EXPECT_NO_THROW(sf.result()); + } + + EXPECT_TRUE(executed->load()); + + sf.wait(); } // 测试 futureBase 接口的 waitFor 方法 From a1dfb3ac84fc737b638bea8ead2d9913b61ff233 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 22:57:29 +0800 Subject: [PATCH 52/81] fix: Correct platform logic --- test/unit_test/test_vibrant/test_thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_test/test_vibrant/test_thread.cpp b/test/unit_test/test_vibrant/test_thread.cpp index d206311..97d24b8 100644 --- a/test/unit_test/test_vibrant/test_thread.cpp +++ b/test/unit_test/test_vibrant/test_thread.cpp @@ -478,7 +478,7 @@ TEST_F(ThreadTest, PlatformThreadPrintableInterface) { thread_type pt1([] {}); thread_type pt2; - const std::string platform_thread_name = ON_WINDOWS() ? "wThread": "pThread"; + const std::string platform_thread_name = USING_MSVC() ? "wThread": "pThread"; // Test className ASSERT_EQ(pt1.className(), platform_thread_name); From 2c4c2c29fc58d9dc426cb20e140b595ff4961e35 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 22:57:46 +0800 Subject: [PATCH 53/81] refactor: Using thread::sleep --- test/unit_test/test_vibrant/test_thread.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit_test/test_vibrant/test_thread.cpp b/test/unit_test/test_vibrant/test_thread.cpp index 97d24b8..8ff5c37 100644 --- a/test/unit_test/test_vibrant/test_thread.cpp +++ b/test/unit_test/test_vibrant/test_thread.cpp @@ -58,7 +58,7 @@ namespace { // Function with delay for join/detach tests void delayedFunction(std::atomic& flag) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + thread::sleep(milliseconds(500)); flag = true; } } @@ -161,7 +161,7 @@ TEST_F(ThreadTest, Detach) { ASSERT_FALSE(t); } // Give some time for the thread to complete - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + thread::sleep(milliseconds(1000)); ASSERT_TRUE(flag); } @@ -183,7 +183,7 @@ TEST_F(ThreadTest, DestructorDetach) { // t will be detached when it goes out of scope } // Give some time for the thread to complete - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + thread::sleep(milliseconds(1000)); ASSERT_TRUE(flag); } @@ -243,14 +243,14 @@ TEST_F(ThreadTest, WillJoinFlag) { // Will be detached on destruction } // Give some time for the thread to complete - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + thread::sleep(microseconds(200)); ASSERT_TRUE(flag); } // Test thread ID uniqueness TEST_F(ThreadTest, ThreadIdUniqueness) { - thread t1([] { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }); - thread t2([] { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }); + thread t1([] { thread::sleep(microseconds(100)); }); + thread t2([] { thread::sleep(microseconds(100)); }); const ul_integer id1 = t1.id(); const ul_integer id2 = t2.id(); From cae324918ffa9887f03d7cafee62588285c7198a Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 23:01:50 +0800 Subject: [PATCH 54/81] refactor: Using compile-time type detection --- src/vibrant/condition.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/vibrant/condition.h b/src/vibrant/condition.h index b9c303a..fda5e63 100644 --- a/src/vibrant/condition.h +++ b/src/vibrant/condition.h @@ -273,12 +273,9 @@ inline original::pCondition::pCondition() : cond_{} inline void original::pCondition::wait(mutexBase& mutex) { - const auto p_mutex = dynamic_cast(&mutex); - if (!p_mutex) { - throw valueError("Invalid mutex type for condition variable: must be pMutex"); - } + staticError>::asserts(); - const auto handle = static_cast(p_mutex->nativeHandle()); + const auto handle = static_cast(mutex.nativeHandle()); if (const int code = pthread_cond_wait(&this->cond_, handle); code != 0) { throw sysError("Failed to wait on condition variable (pthread_cond_wait returned " + printable::formatString(code) + ")"); } @@ -286,14 +283,11 @@ inline void original::pCondition::wait(mutexBase& mutex) inline bool original::pCondition::waitFor(mutexBase& mutex, const time::duration d) { - const auto p_mutex = dynamic_cast(&mutex); - if (!p_mutex) { - throw valueError("Invalid mutex type for condition variable: must be pMutex"); - } + staticError>::asserts(); const auto deadline = time::point::now() + d; const auto ts = deadline.toTimespec(); - const auto handle = static_cast(p_mutex->nativeHandle()); + const auto handle = static_cast(mutex.nativeHandle()); const int code = pthread_cond_timedwait(&this->cond_, handle, &ts); if (code == 0) return true; if (code == ETIMEDOUT) return false; From 5b209c8206221b78f2fa2147457d7e6a2efffe38 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 23:03:00 +0800 Subject: [PATCH 55/81] refactor: Using const lvalue reference --- src/vibrant/async.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vibrant/async.h b/src/vibrant/async.h index ae79a85..01cba37 100644 --- a/src/vibrant/async.h +++ b/src/vibrant/async.h @@ -487,7 +487,7 @@ namespace original { * @return A new future holding the result of the callback */ template - auto operator|(async::sharedFuture sf, Callback&& c); + auto operator|(const async::sharedFuture& sf, Callback&& c); /** * @brief Pipe operator specialization for sharedFuture @@ -501,7 +501,7 @@ namespace original { * @return A new future holding the result of the callback */ template - auto operator|(async::sharedFuture sf, Callback&& c); + auto operator|(const async::sharedFuture& sf, Callback&& c); /** * @brief Lazy pipe operator for chaining promise computations @@ -1194,7 +1194,7 @@ auto original::operator|(async::future f, Callback&& c) } template -auto original::operator|(async::sharedFuture sf, Callback&& c) +auto original::operator|(const async::sharedFuture& sf, Callback&& c) { using ResultType = std::invoke_result_t; return async::get([sf, c = std::forward(c)] mutable -> ResultType { @@ -1203,7 +1203,7 @@ auto original::operator|(async::sharedFuture sf, Callback&& c) } template -auto original::operator|(async::sharedFuture sf, Callback&& c) +auto original::operator|(const async::sharedFuture& sf, Callback&& c) { using ResultType = std::invoke_result_t; return async::get([sf, c = std::forward(c)]() mutable -> ResultType { From 9b0cc035f906fdb785ebd6b8b94ee61edf4f67e2 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 23:04:22 +0800 Subject: [PATCH 56/81] refactor: Using const lvalue reference --- src/vibrant/async.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vibrant/async.h b/src/vibrant/async.h index 01cba37..7bc0e15 100644 --- a/src/vibrant/async.h +++ b/src/vibrant/async.h @@ -48,7 +48,7 @@ namespace original { * @brief Sets an exception and marks as ready * @param e Exception pointer to store */ - void setException(std::exception_ptr e); + void setException(const std::exception_ptr& e); /** * @brief Checks if the result is ready @@ -572,7 +572,7 @@ namespace original { * @brief Sets an exception and marks as completed * @param e Exception pointer to store */ - void setException(std::exception_ptr e); + void setException(const std::exception_ptr& e); /** * @brief Checks if the computation is completed @@ -838,11 +838,11 @@ void original::async::asyncWrapper::setValue(TYPE&& v) } template -void original::async::asyncWrapper::setException(std::exception_ptr e) +void original::async::asyncWrapper::setException(const std::exception_ptr &e) { { uniqueLock lock{this->mutex_}; - this->e_ = std::move(e); + this->e_ = e; this->ready_.store(true); } this->cond_.notifyAll(); @@ -1249,11 +1249,11 @@ inline void original::async::asyncWrapper::setValue() this->cond_.notifyAll(); } -inline void original::async::asyncWrapper::setException(std::exception_ptr e) +inline void original::async::asyncWrapper::setException(const std::exception_ptr& e) { { uniqueLock lock{this->mutex_}; - this->e_ = std::move(e); + this->e_ = e; this->ready_.store(true); } this->cond_.notifyAll(); From a049e735632ed8ce43a40beb6542647acf21c3e8 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Fri, 10 Oct 2025 23:23:28 +0800 Subject: [PATCH 57/81] refactor: Adjust the initialization sequence --- src/core/chain.h | 7 ++++++- src/core/forwardChain.h | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/chain.h b/src/core/chain.h index 581ee41..b92083d 100644 --- a/src/core/chain.h +++ b/src/core/chain.h @@ -591,7 +591,12 @@ namespace std { } template - original::chain::chain(ALLOC alloc) : baseList(std::move(alloc)), size_(0), rebind_alloc(std::move(rebind_alloc_node{})) + original::chain::chain(ALLOC alloc) + : baseList(std::move(alloc)), + size_(0), + begin_(nullptr), + end_(nullptr), + rebind_alloc(std::move(rebind_alloc_node{})) { chainInit(); } diff --git a/src/core/forwardChain.h b/src/core/forwardChain.h index a00e4ee..eee4eda 100644 --- a/src/core/forwardChain.h +++ b/src/core/forwardChain.h @@ -559,7 +559,10 @@ namespace original { template original::forwardChain::forwardChain(ALLOC alloc) - : baseList(std::move(alloc)), size_(0) , rebind_alloc(std::move(rebind_alloc_node{})) + : baseList(std::move(alloc)), + size_(0), + begin_(nullptr), + rebind_alloc(std::move(rebind_alloc_node{})) { this->chainInit(); } From 97fb3926ff72d9732354d72da8c33da801f9c6ed Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Sat, 11 Oct 2025 14:21:14 +0800 Subject: [PATCH 58/81] chore: Add MVP gdb formatter scripts --- .gdbinit | 7 +++++++ debug/gdbinit.py | 14 ++++++++++++++ debug/printers/core/couple_printer.py | 17 +++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 .gdbinit create mode 100644 debug/gdbinit.py create mode 100644 debug/printers/core/couple_printer.py diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..bdf921c --- /dev/null +++ b/.gdbinit @@ -0,0 +1,7 @@ +python +import sys +import os +sys.path.insert(0, os.path.join(os.getcwd(), 'debug')) +import gdbinit +print("GDB pretty-printer for original initialized.") +end \ No newline at end of file diff --git a/debug/gdbinit.py b/debug/gdbinit.py new file mode 100644 index 0000000..d8fb269 --- /dev/null +++ b/debug/gdbinit.py @@ -0,0 +1,14 @@ +import gdb +import sys +import os + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "printers")) + +from core import couple_printer + +pp = gdb.printing.RegexpCollectionPrettyPrinter("original") +pp.add_printer('couple', '^original::couple<.*>$', couple_printer.CouplePrinter) + +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) + +print("GDB pretty-printer for original registered.") \ No newline at end of file diff --git a/debug/printers/core/couple_printer.py b/debug/printers/core/couple_printer.py new file mode 100644 index 0000000..481b759 --- /dev/null +++ b/debug/printers/core/couple_printer.py @@ -0,0 +1,17 @@ +# debug\printers\core\couple_printer.py +import gdb + +class CouplePrinter: + """Pretty printer for original::couple""" + + def __init__(self, val): + self.val = val + + def to_string(self): + first = self.val['first_'] + second = self.val['second_'] + return f"original::couple({first}, {second})" + + def children(self): + yield "first", self.val['first_'] + yield "second", self.val['second_'] \ No newline at end of file From dcb68f29b260789eb368a85c2620fabe535215de Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Sat, 11 Oct 2025 14:21:55 +0800 Subject: [PATCH 59/81] chore: Add new exclusive directories --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6b24f6f..a79dd3a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ install/ .vscode/ out/ original/ +**/__pycache__/ test.exe original.zip From 4371ffe1c15d5e85d056ac0aa06a21864841d09c Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Sat, 11 Oct 2025 14:22:32 +0800 Subject: [PATCH 60/81] chore: Extract testing config --- CMakeLists.txt | 18 +----------------- test/CMakeLists.txt | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e2bc12..7f0900e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,21 +76,5 @@ install(FILES option(BUILD_TESTING "Build the testing directories" ON) if (BUILD_TESTING) - include(CTest) - if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") - else() - if (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -g") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") - endif() - endif() - - # test cases - add_subdirectory(test/other) - add_subdirectory(test/unit_test) + add_subdirectory(test) endif () \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..8153c15 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,19 @@ +# test/CMakeLists.txt + +include(CTest) +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") +else() + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -g") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + endif() +endif() + +# test cases +add_subdirectory(other) +add_subdirectory(unit_test) \ No newline at end of file From 30362a991693d0a906d9bcb87aa34eb43d0d5d12 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Mon, 13 Oct 2025 17:43:26 +0800 Subject: [PATCH 61/81] chore: Add all clion build directories to exclusive list --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a79dd3a..1d69fda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -cmake-build-debug/ +cmake-build-*/ .idea/ build/ install/ From cadc4e7c4a8bf6d76a412b4fa740f3daa8216bd2 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Mon, 13 Oct 2025 17:44:33 +0800 Subject: [PATCH 62/81] chore: Add register logic for all printers --- debug/gdbinit.py | 56 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/debug/gdbinit.py b/debug/gdbinit.py index d8fb269..aba8d0e 100644 --- a/debug/gdbinit.py +++ b/debug/gdbinit.py @@ -1,14 +1,58 @@ +# debug/gdbinit.py + import gdb import sys import os +import importlib.util +import inspect -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "printers")) -from core import couple_printer +def load_printers_from_directory(pretty_printer_collection, directory): + """Load all pretty-printer scripts from the specified directory.""" + if not os.path.isdir(directory): + print(f"[WARN] Skipped non-existent directory: {directory}") + return -pp = gdb.printing.RegexpCollectionPrettyPrinter("original") -pp.add_printer('couple', '^original::couple<.*>$', couple_printer.CouplePrinter) + for file_name in os.listdir(directory): + if not file_name.endswith("_printer.py"): + continue + + file_path = os.path.join(directory, file_name) + module_name = os.path.splitext(file_name)[0] + + try: + spec = importlib.util.spec_from_file_location(module_name, file_path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + printer_class = None + for name, cls in inspect.getmembers(module, inspect.isclass): + if name == "Printer": + printer_class = cls + break + + if printer_class is None: + print(f"[SKIP] {module_name}: no 'Printer' class found") + continue + type_name = module_name.replace("_printer", "") + type_regex = f"^original::{type_name}(<.*>)?$" -gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) + pretty_printer_collection.add_printer(module_name, type_regex, printer_class) + print(f"Registered pretty-printer: {type_name} -> {printer_class.__name__}") + + except Exception as e: + print(f"Failed to load {file_name}: {e}") + + +this_dir = os.path.dirname(__file__) +printers_dir = os.path.join(this_dir, "printers") +core_dir = os.path.join(printers_dir, "core") + +sys.path.insert(0, printers_dir) +sys.path.insert(0, core_dir) + +pp = gdb.printing.RegexpCollectionPrettyPrinter("original") +load_printers_from_directory(pp, core_dir) +gdb.printing.register_pretty_printer(None, pp) -print("GDB pretty-printer for original registered.") \ No newline at end of file +print("GDB pretty-printers for 'original' registered successfully.") \ No newline at end of file From bda8cca7e18b1600108cd0ed6b6307eb8133899e Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Mon, 13 Oct 2025 17:45:30 +0800 Subject: [PATCH 63/81] chore: Add auto-load permissions for setting up GDB --- CMakeLists.txt | 2 ++ debug/CMakeLists.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 debug/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f0900e..f7c48a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,8 @@ install(FILES DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/original ) +add_subdirectory(debug) + option(BUILD_TESTING "Build the testing directories" ON) if (BUILD_TESTING) diff --git a/debug/CMakeLists.txt b/debug/CMakeLists.txt new file mode 100644 index 0000000..2843c8d --- /dev/null +++ b/debug/CMakeLists.txt @@ -0,0 +1,42 @@ +# debug/CMakeLists.txt + +if(CMAKE_BUILD_TYPE MATCHES "Debug") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "MinGW") + message(STATUS "[GDB CONFIG] Detected GNU/MinGW toolchain, setting up GDB auto-load permissions") + + if(WIN32) + file(TO_CMAKE_PATH "$ENV{USERPROFILE}" USER_HOME) + else() + file(TO_CMAKE_PATH "$ENV{HOME}" USER_HOME) + endif() + + set(GDB_GLOBAL_INIT "${USER_HOME}/.config/gdb/gdbinit") + if(NOT EXISTS "${GDB_GLOBAL_INIT}") + set(GDB_GLOBAL_INIT "${USER_HOME}/.gdbinit") + endif() + + set(PROJECT_GDBINIT "${CMAKE_SOURCE_DIR}/.gdbinit") + + set(GDB_CONFIG_LINES + "set auto-load local-gdbinit on +add-auto-load-safe-path ${PROJECT_GDBINIT}\n" + ) + + get_filename_component(GDB_CONFIG_DIR "${GDB_GLOBAL_INIT}" DIRECTORY) + file(MAKE_DIRECTORY "${GDB_CONFIG_DIR}") + + if(EXISTS "${GDB_GLOBAL_INIT}") + file(READ "${GDB_GLOBAL_INIT}" EXISTING_CONTENT) + string(FIND "${EXISTING_CONTENT}" "${PROJECT_GDBINIT}" ALREADY_ADDED) + else() + set(ALREADY_ADDED -1) + endif() + + if(ALREADY_ADDED EQUAL -1) + file(APPEND "${GDB_GLOBAL_INIT}" "\n# Added by Original CMake auto-config\n${GDB_CONFIG_LINES}") + message(STATUS "[GDB CONFIG] Added safe-path for ${PROJECT_GDBINIT} in ${GDB_GLOBAL_INIT}") + else() + message(STATUS "[GDB CONFIG] Safe-path already configured in ${GDB_GLOBAL_INIT}") + endif() + endif() +endif() From 404ff42e20c66722609926a3f08c05362c6c5d1e Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Mon, 13 Oct 2025 17:46:18 +0800 Subject: [PATCH 64/81] chore: Add pretty printers for auto pointers, couple and tuple --- debug/printers/core/autoPtr_printer.py | 46 ++++++++++++++++++++++++ debug/printers/core/couple_printer.py | 16 +++++---- debug/printers/core/ownerPtr_printer.py | 15 ++++++++ debug/printers/core/strongPtr_printer.py | 15 ++++++++ debug/printers/core/tuple_printer.py | 33 +++++++++++++++++ debug/printers/core/weakPtr_printer.py | 15 ++++++++ debug/printers/utils.py | 9 +++++ 7 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 debug/printers/core/autoPtr_printer.py create mode 100644 debug/printers/core/ownerPtr_printer.py create mode 100644 debug/printers/core/strongPtr_printer.py create mode 100644 debug/printers/core/tuple_printer.py create mode 100644 debug/printers/core/weakPtr_printer.py create mode 100644 debug/printers/utils.py diff --git a/debug/printers/core/autoPtr_printer.py b/debug/printers/core/autoPtr_printer.py new file mode 100644 index 0000000..86146c1 --- /dev/null +++ b/debug/printers/core/autoPtr_printer.py @@ -0,0 +1,46 @@ +# debug/printers/core/autoPtr_printer.py + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + +class PrinterBase: + """Pretty printer for derived classes of autoPtr in original""" + + def __init__(self, val): + self.val = val + + def class_name(self): + pass + + def to_string(self): + ptr = int(gdb.parse_and_eval(f'(({self.val.type.name}*)({int(self.val.address)}))->get()')) + if ptr != 0: + return f"{self.class_name()}(@{ptr:#x})" + else: + return f"{self.class_name()}(nullptr)" + + + def children(self): + ptr = gdb.parse_and_eval(f'(({self.val.type.name}*)({int(self.val.address)}))->get()') + ptr_val = int(ptr) + yield "pointer", f"{ptr_val:#x}" if ptr_val != 0 else "nullptr" + + if ptr_val != 0: + yield "object", ptr.dereference() + + ref_count = self.val['ref_count'] + loaded_ptr = gdb.parse_and_eval(f'(({ref_count.type.name}*)({int(ref_count.address)}))->operator*()') + + try: + ref_count_base = loaded_ptr.dereference() + strong_refs_atomic = ref_count_base['strong_refs'] + weak_refs_atomic = ref_count_base['weak_refs'] + strong_refs = gdb.parse_and_eval(f"(({strong_refs_atomic.type.name}*)({int(strong_refs_atomic.address)}))->operator*()") + weak_refs = gdb.parse_and_eval(f"(({weak_refs_atomic.type.name}*)({int(weak_refs_atomic.address)}))->operator*()") + yield "strong_refs", to_int(strong_refs, U_INTEGER_SIZE) + yield "weak_refs", to_int(weak_refs, U_INTEGER_SIZE) + except gdb.error as e: + yield "ref_count_details", f"[cannot access: {e}]" \ No newline at end of file diff --git a/debug/printers/core/couple_printer.py b/debug/printers/core/couple_printer.py index 481b759..946858f 100644 --- a/debug/printers/core/couple_printer.py +++ b/debug/printers/core/couple_printer.py @@ -1,17 +1,19 @@ -# debug\printers\core\couple_printer.py +# debug/printers/core/couple_printer.py + import gdb -class CouplePrinter: +class Printer: """Pretty printer for original::couple""" def __init__(self, val): self.val = val def to_string(self): - first = self.val['first_'] - second = self.val['second_'] - return f"original::couple({first}, {second})" + return f"original::couple(@{int(self.val.address):#x})" def children(self): - yield "first", self.val['first_'] - yield "second", self.val['second_'] \ No newline at end of file + yield "[0]", self.val['first_'] + yield "[1]", self.val['second_'] + + def display_hint(self): + return "array" \ No newline at end of file diff --git a/debug/printers/core/ownerPtr_printer.py b/debug/printers/core/ownerPtr_printer.py new file mode 100644 index 0000000..49d82f8 --- /dev/null +++ b/debug/printers/core/ownerPtr_printer.py @@ -0,0 +1,15 @@ +# debug/printers/core/ownerPtr_printer.py + +import gdb + +from autoPtr_printer import PrinterBase as Base +class Printer(Base): + """Pretty printer for original::ownerPtr""" + + + def __init__(self, val): + super().__init__(val) + + + def class_name(self): + return "original::ownerPtr" \ No newline at end of file diff --git a/debug/printers/core/strongPtr_printer.py b/debug/printers/core/strongPtr_printer.py new file mode 100644 index 0000000..629c30b --- /dev/null +++ b/debug/printers/core/strongPtr_printer.py @@ -0,0 +1,15 @@ +# debug/printers/core/strongPtr_printer.py + +import gdb + +from autoPtr_printer import PrinterBase as Base +class Printer(Base): + """Pretty printer for original::strongPtr""" + + + def __init__(self, val): + super().__init__(val) + + + def class_name(self): + return "original::strongPtr" \ No newline at end of file diff --git a/debug/printers/core/tuple_printer.py b/debug/printers/core/tuple_printer.py new file mode 100644 index 0000000..f2b28c0 --- /dev/null +++ b/debug/printers/core/tuple_printer.py @@ -0,0 +1,33 @@ +# debug/printers/core/tuple_printer.py + +import gdb + +class Printer: + """Pretty printer for original::tuple""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::tuple(@{int(self.val.address):#x})" + + def children(self): + elems = self.val['elems'] + elems_list = [] + current = elems + index = 0 + while True: + try: + elem = current['cur_elem'] + elems_list.append(elem) + current = current['next'] + index += 1 + except gdb.error: + break + + yield "size", index + for i, e in enumerate(elems_list): + yield f"[{i}]", e + + def display_hint(self): + return None \ No newline at end of file diff --git a/debug/printers/core/weakPtr_printer.py b/debug/printers/core/weakPtr_printer.py new file mode 100644 index 0000000..2333413 --- /dev/null +++ b/debug/printers/core/weakPtr_printer.py @@ -0,0 +1,15 @@ +# debug/printers/core/weakPtr_printer.py + +import gdb + +from autoPtr_printer import PrinterBase as Base +class Printer(Base): + """Pretty printer for original::weakPtr""" + + + def __init__(self, val): + super().__init__(val) + + + def class_name(self): + return "original::weakPtr" \ No newline at end of file diff --git a/debug/printers/utils.py b/debug/printers/utils.py new file mode 100644 index 0000000..621dd58 --- /dev/null +++ b/debug/printers/utils.py @@ -0,0 +1,9 @@ +# debug/printers/utils.py + + +U_INTEGER_SIZE = 4 + +def to_int(val, size = 8): + mask = (1 << (size * 8)) - 1 + v = int(val) + return v & mask \ No newline at end of file From df75c24885d08c1acb84f1e2ee4605374587a096 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:12:38 +0800 Subject: [PATCH 65/81] chore: Add all clion tmp directories to exclusive list --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1d69fda..6792be8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ cmake-build-*/ -.idea/ +**/.idea/ build/ install/ .vs/ From 58631dca32a3d5ec9d1d85bf89565ffd3c86ffdc Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:13:45 +0800 Subject: [PATCH 66/81] feat: Add helper functions in utils.py --- debug/printers/utils.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/debug/printers/utils.py b/debug/printers/utils.py index 621dd58..b071bed 100644 --- a/debug/printers/utils.py +++ b/debug/printers/utils.py @@ -1,9 +1,30 @@ # debug/printers/utils.py +import gdb + U_INTEGER_SIZE = 4 def to_int(val, size = 8): mask = (1 << (size * 8)) - 1 v = int(val) - return v & mask \ No newline at end of file + return v & mask + +def address(obj): + try: + return int(obj.address) if obj.address else None + except gdb.error: + return None + +def type_name(obj): + return obj.type.name + +def call(obj, method_name, *args): + try: + args_str = ', '.join(str(arg) for arg in args) + addr = address(obj) + expr = f'(({type_name(obj)}*)({addr}))->{method_name}({args_str})' + return gdb.parse_and_eval(expr) + except Exception as e: + print(f"Error calling {method_name} on {obj}: {e}") + return None From 6f58f898579af1f71d0427c762b728e337865e97 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:14:12 +0800 Subject: [PATCH 67/81] refactor: Remove redundant info --- debug/gdbinit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug/gdbinit.py b/debug/gdbinit.py index aba8d0e..c9a86d9 100644 --- a/debug/gdbinit.py +++ b/debug/gdbinit.py @@ -38,7 +38,7 @@ def load_printers_from_directory(pretty_printer_collection, directory): type_regex = f"^original::{type_name}(<.*>)?$" pretty_printer_collection.add_printer(module_name, type_regex, printer_class) - print(f"Registered pretty-printer: {type_name} -> {printer_class.__name__}") + print(f"Registered pretty-printer: {type_name}") except Exception as e: print(f"Failed to load {file_name}: {e}") From a4918dcb42ac142ecf8530585c813a070dfac6ac Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:15:00 +0800 Subject: [PATCH 68/81] refactor: Use helpers in utils.py --- debug/printers/core/couple_printer.py | 7 ++++++- debug/printers/core/tuple_printer.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/debug/printers/core/couple_printer.py b/debug/printers/core/couple_printer.py index 946858f..aa819cc 100644 --- a/debug/printers/core/couple_printer.py +++ b/debug/printers/core/couple_printer.py @@ -1,6 +1,11 @@ # debug/printers/core/couple_printer.py import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + class Printer: """Pretty printer for original::couple""" @@ -9,7 +14,7 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::couple(@{int(self.val.address):#x})" + return f"original::couple(@{address(self.val):#x})" def children(self): yield "[0]", self.val['first_'] diff --git a/debug/printers/core/tuple_printer.py b/debug/printers/core/tuple_printer.py index f2b28c0..9fb2d81 100644 --- a/debug/printers/core/tuple_printer.py +++ b/debug/printers/core/tuple_printer.py @@ -1,6 +1,11 @@ # debug/printers/core/tuple_printer.py import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + class Printer: """Pretty printer for original::tuple""" @@ -9,7 +14,7 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::tuple(@{int(self.val.address):#x})" + return f"original::tuple(@{address(self.val):#x})" def children(self): elems = self.val['elems'] From 95a06d499407d4cb8e26a4c91b24f23ce7c97c6c Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:15:37 +0800 Subject: [PATCH 69/81] fix: Fix show bugs in printer of autoPtr --- debug/printers/core/autoPtr_printer.py | 35 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/debug/printers/core/autoPtr_printer.py b/debug/printers/core/autoPtr_printer.py index 86146c1..366e179 100644 --- a/debug/printers/core/autoPtr_printer.py +++ b/debug/printers/core/autoPtr_printer.py @@ -6,6 +6,21 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) from utils import * + +def is_array_ptr(val): + type_str = str(val.type) + + if "<" not in type_str or ">" not in type_str: + return False + + inner = type_str[type_str.find("<")+1:type_str.rfind(">")] + parts = [p.strip() for p in inner.split(",")] + if len(parts) < 2: + return False + deleter_param = parts[1] + return deleter_param.endswith("[]>") + + class PrinterBase: """Pretty printer for derived classes of autoPtr in original""" @@ -13,33 +28,35 @@ def __init__(self, val): self.val = val def class_name(self): - pass + return "original::autoPtr" def to_string(self): - ptr = int(gdb.parse_and_eval(f'(({self.val.type.name}*)({int(self.val.address)}))->get()')) + ptr = int(call(self.val, "get")) if ptr != 0: return f"{self.class_name()}(@{ptr:#x})" else: return f"{self.class_name()}(nullptr)" - def children(self): - ptr = gdb.parse_and_eval(f'(({self.val.type.name}*)({int(self.val.address)}))->get()') + ptr = call(self.val, "get") ptr_val = int(ptr) - yield "pointer", f"{ptr_val:#x}" if ptr_val != 0 else "nullptr" if ptr_val != 0: - yield "object", ptr.dereference() + if is_array_ptr(self.val): + yield "array", f"@{ptr_val:#x}" + else: + yield "pointer", f"@{ptr_val:#x}" if ptr_val != 0 else "nullptr" + yield "object", ptr.dereference() ref_count = self.val['ref_count'] - loaded_ptr = gdb.parse_and_eval(f'(({ref_count.type.name}*)({int(ref_count.address)}))->operator*()') + loaded_ptr = call(ref_count, "operator*") try: ref_count_base = loaded_ptr.dereference() strong_refs_atomic = ref_count_base['strong_refs'] weak_refs_atomic = ref_count_base['weak_refs'] - strong_refs = gdb.parse_and_eval(f"(({strong_refs_atomic.type.name}*)({int(strong_refs_atomic.address)}))->operator*()") - weak_refs = gdb.parse_and_eval(f"(({weak_refs_atomic.type.name}*)({int(weak_refs_atomic.address)}))->operator*()") + strong_refs = call(strong_refs_atomic, "operator*") + weak_refs = call(weak_refs_atomic, "operator*") yield "strong_refs", to_int(strong_refs, U_INTEGER_SIZE) yield "weak_refs", to_int(weak_refs, U_INTEGER_SIZE) except gdb.error as e: From 34fe81813ba322d17b3a9a9573c0dbc597b3b170 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 00:16:28 +0800 Subject: [PATCH 70/81] feat: Add pretty printer for serial containers and container adaptors --- debug/printers/core/array_printer.py | 30 ++++++++++++++++ debug/printers/core/bitSet_printer.py | 27 ++++++++++++++ debug/printers/core/blocksList_printer.py | 35 +++++++++++++++++++ debug/printers/core/chain_printer.py | 29 +++++++++++++++ .../printers/core/containerAdaptor_printer.py | 23 ++++++++++++ debug/printers/core/deque_printerr.py | 14 ++++++++ debug/printers/core/forwardChain_printer.py | 28 +++++++++++++++ debug/printers/core/prique_printer.py | 14 ++++++++ debug/printers/core/queue_printer.py | 14 ++++++++ debug/printers/core/stack_printer.py | 14 ++++++++ debug/printers/core/vector_printer.py | 32 +++++++++++++++++ 11 files changed, 260 insertions(+) create mode 100644 debug/printers/core/array_printer.py create mode 100644 debug/printers/core/bitSet_printer.py create mode 100644 debug/printers/core/blocksList_printer.py create mode 100644 debug/printers/core/chain_printer.py create mode 100644 debug/printers/core/containerAdaptor_printer.py create mode 100644 debug/printers/core/deque_printerr.py create mode 100644 debug/printers/core/forwardChain_printer.py create mode 100644 debug/printers/core/prique_printer.py create mode 100644 debug/printers/core/queue_printer.py create mode 100644 debug/printers/core/stack_printer.py create mode 100644 debug/printers/core/vector_printer.py diff --git a/debug/printers/core/array_printer.py b/debug/printers/core/array_printer.py new file mode 100644 index 0000000..fe92316 --- /dev/null +++ b/debug/printers/core/array_printer.py @@ -0,0 +1,30 @@ +# debug/printers/core/array_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::array""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::array(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + for i in range(0, size): + v = call(self.val, "operator[]", f"{i}") + if v.type.code == gdb.TYPE_CODE_REF: + v = v.referenced_value() + yield f"[{i}]", v + + def display_hint(self): + return "array" \ No newline at end of file diff --git a/debug/printers/core/bitSet_printer.py b/debug/printers/core/bitSet_printer.py new file mode 100644 index 0000000..17f3157 --- /dev/null +++ b/debug/printers/core/bitSet_printer.py @@ -0,0 +1,27 @@ +# debug/printers/core/bitSet_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::bitset""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::bitset(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + for i in range(0, size): + yield f"[{i}]", call(self.val, "get", f"{i}") + + def display_hint(self): + return "array" \ No newline at end of file diff --git a/debug/printers/core/blocksList_printer.py b/debug/printers/core/blocksList_printer.py new file mode 100644 index 0000000..aab3b6b --- /dev/null +++ b/debug/printers/core/blocksList_printer.py @@ -0,0 +1,35 @@ +# debug/printers/core/blocksList_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::blocksList""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::blocksList(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + for i in range(0, size): + v = call(self.val, "operator[]", f"{i}") + if v.type.code == gdb.TYPE_CODE_REF: + v = v.referenced_value() + yield f"[{i}]", v + + yield "first", self.val["first_"] + yield "last", self.val["last_"] + yield "first block", self.val["first_block"] + yield "last block", self.val["last_block"] + + def display_hint(self): + return "array" \ No newline at end of file diff --git a/debug/printers/core/chain_printer.py b/debug/printers/core/chain_printer.py new file mode 100644 index 0000000..f862590 --- /dev/null +++ b/debug/printers/core/chain_printer.py @@ -0,0 +1,29 @@ +# debug/printers/core/chain_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::chain""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::chain(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + p = self.val["begin_"] + for i in range(0, size): + node = p.dereference() + yield f"[{i}]", node["data_"] + p = node["next"] + yield "begin", self.val["begin_"] + yield "end", self.val["end_"] \ No newline at end of file diff --git a/debug/printers/core/containerAdaptor_printer.py b/debug/printers/core/containerAdaptor_printer.py new file mode 100644 index 0000000..0c2ff02 --- /dev/null +++ b/debug/printers/core/containerAdaptor_printer.py @@ -0,0 +1,23 @@ +# debug/printers/core/containerAdaptor_printer.py + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class PrinterBase: + """Pretty printer for derived classes of containerAdaptor in original""" + + def __init__(self, val): + self.val = val + + def class_name(self): + return "original::containerAdaptor" + + def to_string(self): + return f"{self.class_name()}(@{address(self.val):#x})" + + def children(self): + yield "serial", self.val["serial_"] \ No newline at end of file diff --git a/debug/printers/core/deque_printerr.py b/debug/printers/core/deque_printerr.py new file mode 100644 index 0000000..9dc04dd --- /dev/null +++ b/debug/printers/core/deque_printerr.py @@ -0,0 +1,14 @@ +# debug/printers/core/deque_printer.py + +import gdb +from containerAdaptor_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::deque""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::deque" \ No newline at end of file diff --git a/debug/printers/core/forwardChain_printer.py b/debug/printers/core/forwardChain_printer.py new file mode 100644 index 0000000..ea13649 --- /dev/null +++ b/debug/printers/core/forwardChain_printer.py @@ -0,0 +1,28 @@ +# debug/printers/core/forwardChain_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::forwardChain""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::forwardChain(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + p = self.val["begin_"] + for i in range(0, size): + node = p.dereference() + yield f"[{i}]", node["data_"] + p = node["next"] + yield "begin", self.val["begin_"] \ No newline at end of file diff --git a/debug/printers/core/prique_printer.py b/debug/printers/core/prique_printer.py new file mode 100644 index 0000000..a125f5d --- /dev/null +++ b/debug/printers/core/prique_printer.py @@ -0,0 +1,14 @@ +# debug/printers/core/prique_printer.py + +import gdb +from containerAdaptor_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::prique""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::prique" \ No newline at end of file diff --git a/debug/printers/core/queue_printer.py b/debug/printers/core/queue_printer.py new file mode 100644 index 0000000..f9a6e45 --- /dev/null +++ b/debug/printers/core/queue_printer.py @@ -0,0 +1,14 @@ +# debug/printers/core/queue_printer.py + +import gdb +from containerAdaptor_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::queue""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::queue" \ No newline at end of file diff --git a/debug/printers/core/stack_printer.py b/debug/printers/core/stack_printer.py new file mode 100644 index 0000000..7fcba7d --- /dev/null +++ b/debug/printers/core/stack_printer.py @@ -0,0 +1,14 @@ +# debug/printers/core/stack_printer.py + +import gdb +from containerAdaptor_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::stack""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::stack" \ No newline at end of file diff --git a/debug/printers/core/vector_printer.py b/debug/printers/core/vector_printer.py new file mode 100644 index 0000000..20097d6 --- /dev/null +++ b/debug/printers/core/vector_printer.py @@ -0,0 +1,32 @@ +# debug/printers/core/vector_printer.py + + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer: + """Pretty printer for original::vector""" + + def __init__(self, val): + self.val = val + + def to_string(self): + return f"original::vector(@{address(self.val):#x})" + + def children(self): + size = int(call(self.val, "size")) + yield "size", size + for i in range(0, size): + v = call(self.val, "operator[]", f"{i}") + if v.type.code == gdb.TYPE_CODE_REF: + v = v.referenced_value() + yield f"[{i}]", v + yield "max size", self.val["max_size"] + yield "inner begin", self.val["inner_begin"] + + def display_hint(self): + return "array" \ No newline at end of file From 475f34975fef6fab6bacfb622a081d1f19a1deaa Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 14:29:43 +0800 Subject: [PATCH 71/81] feat: Add helper to print address --- debug/printers/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debug/printers/utils.py b/debug/printers/utils.py index b071bed..0157052 100644 --- a/debug/printers/utils.py +++ b/debug/printers/utils.py @@ -16,6 +16,11 @@ def address(obj): except gdb.error: return None +def addr_str(item): + if isinstance(item, int) or isinstance(item, str): + return f"@{item:#x}" + return f"@{address(item):#x}" + def type_name(obj): return obj.type.name From 2a2bb28353b0b700883d2829085af7bb09f64287 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 14:32:27 +0800 Subject: [PATCH 72/81] refactor: Show more info in to_string --- debug/printers/core/array_printer.py | 3 ++- debug/printers/core/autoPtr_printer.py | 14 +++++++++++--- debug/printers/core/bitSet_printer.py | 4 +++- debug/printers/core/blocksList_printer.py | 4 +++- debug/printers/core/chain_printer.py | 3 ++- debug/printers/core/containerAdaptor_printer.py | 2 +- debug/printers/core/couple_printer.py | 2 +- debug/printers/core/forwardChain_printer.py | 2 +- debug/printers/core/tuple_printer.py | 15 ++++++++++++++- debug/printers/core/vector_printer.py | 7 ++++--- 10 files changed, 42 insertions(+), 14 deletions(-) diff --git a/debug/printers/core/array_printer.py b/debug/printers/core/array_printer.py index fe92316..d4487f4 100644 --- a/debug/printers/core/array_printer.py +++ b/debug/printers/core/array_printer.py @@ -15,7 +15,8 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::array(@{address(self.val):#x})" + size = int(call(self.val, "size")) + return f"original::array(cap={size}, {addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) diff --git a/debug/printers/core/autoPtr_printer.py b/debug/printers/core/autoPtr_printer.py index 366e179..bd4f1ef 100644 --- a/debug/printers/core/autoPtr_printer.py +++ b/debug/printers/core/autoPtr_printer.py @@ -32,10 +32,18 @@ def class_name(self): def to_string(self): ptr = int(call(self.val, "get")) - if ptr != 0: - return f"{self.class_name()}(@{ptr:#x})" - else: + if ptr == 0: return f"{self.class_name()}(nullptr)" + ref_count = self.val['ref_count'] + loaded_ptr = call(ref_count, "operator*") + ref_count_base = loaded_ptr.dereference() + strong_refs_atomic = ref_count_base['strong_refs'] + weak_refs_atomic = ref_count_base['weak_refs'] + strong_refs = call(strong_refs_atomic, "operator*") + weak_refs = call(weak_refs_atomic, "operator*") + strong_refs = to_int(strong_refs, U_INTEGER_SIZE) + weak_refs = to_int(weak_refs, U_INTEGER_SIZE) + return f"{self.class_name()}(strong refs={strong_refs}, weak refs={weak_refs}, {addr_str(ptr)})" def children(self): ptr = call(self.val, "get") diff --git a/debug/printers/core/bitSet_printer.py b/debug/printers/core/bitSet_printer.py index 17f3157..15f7335 100644 --- a/debug/printers/core/bitSet_printer.py +++ b/debug/printers/core/bitSet_printer.py @@ -15,7 +15,9 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::bitset(@{address(self.val):#x})" + size = int(call(self.val, "size")) + cnt = int(call(self.val, "count")) + return f"original::bitset(count={cnt}, cap={size}, {addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) diff --git a/debug/printers/core/blocksList_printer.py b/debug/printers/core/blocksList_printer.py index aab3b6b..1695e5d 100644 --- a/debug/printers/core/blocksList_printer.py +++ b/debug/printers/core/blocksList_printer.py @@ -15,7 +15,9 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::blocksList(@{address(self.val):#x})" + size = int(call(self.val, "size")) + capacity = int(call(self.val["map"], "size")) * 16 + return f"original::blocksList(size={size}, cap={capacity}, {addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) diff --git a/debug/printers/core/chain_printer.py b/debug/printers/core/chain_printer.py index f862590..1b63bb4 100644 --- a/debug/printers/core/chain_printer.py +++ b/debug/printers/core/chain_printer.py @@ -15,7 +15,8 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::chain(@{address(self.val):#x})" + size = int(call(self.val, "size")) + return f"original::chain(size={size}, {addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) diff --git a/debug/printers/core/containerAdaptor_printer.py b/debug/printers/core/containerAdaptor_printer.py index 0c2ff02..63bbcfd 100644 --- a/debug/printers/core/containerAdaptor_printer.py +++ b/debug/printers/core/containerAdaptor_printer.py @@ -17,7 +17,7 @@ def class_name(self): return "original::containerAdaptor" def to_string(self): - return f"{self.class_name()}(@{address(self.val):#x})" + return f"{self.class_name()}({addr_str(self.val)})" def children(self): yield "serial", self.val["serial_"] \ No newline at end of file diff --git a/debug/printers/core/couple_printer.py b/debug/printers/core/couple_printer.py index aa819cc..2e62aa9 100644 --- a/debug/printers/core/couple_printer.py +++ b/debug/printers/core/couple_printer.py @@ -14,7 +14,7 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::couple(@{address(self.val):#x})" + return f"original::couple({addr_str(self.val)})" def children(self): yield "[0]", self.val['first_'] diff --git a/debug/printers/core/forwardChain_printer.py b/debug/printers/core/forwardChain_printer.py index ea13649..c428632 100644 --- a/debug/printers/core/forwardChain_printer.py +++ b/debug/printers/core/forwardChain_printer.py @@ -15,7 +15,7 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::forwardChain(@{address(self.val):#x})" + return f"original::forwardChain({addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) diff --git a/debug/printers/core/tuple_printer.py b/debug/printers/core/tuple_printer.py index 9fb2d81..e862893 100644 --- a/debug/printers/core/tuple_printer.py +++ b/debug/printers/core/tuple_printer.py @@ -12,9 +12,22 @@ class Printer: def __init__(self, val): self.val = val + self.size = 0 + try: + elems = val['elems'] + current = elems + while True: + try: + _ = current['cur_elem'] + self.size += 1 + current = current['next'] + except gdb.error: + break + except gdb.error: + self.size = 0 def to_string(self): - return f"original::tuple(@{address(self.val):#x})" + return f"original::tuple(size={self.size}, {addr_str(self.val)})" def children(self): elems = self.val['elems'] diff --git a/debug/printers/core/vector_printer.py b/debug/printers/core/vector_printer.py index 20097d6..dcc2921 100644 --- a/debug/printers/core/vector_printer.py +++ b/debug/printers/core/vector_printer.py @@ -15,7 +15,7 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::vector(@{address(self.val):#x})" + return f"original::vector({addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) @@ -25,8 +25,9 @@ def children(self): if v.type.code == gdb.TYPE_CODE_REF: v = v.referenced_value() yield f"[{i}]", v - yield "max size", self.val["max_size"] - yield "inner begin", self.val["inner_begin"] + if gdb.parameter('print pretty') > 0: + yield "max size", self.val["max_size"] + yield "inner begin", self.val["inner_begin"] def display_hint(self): return "array" \ No newline at end of file From 24718d97f98c538e042799a6cc236fa2289834c0 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 14:33:53 +0800 Subject: [PATCH 73/81] refactor: Optimize the output of the children method --- debug/printers/core/array_printer.py | 3 ++- debug/printers/core/autoPtr_printer.py | 18 +++--------------- debug/printers/core/bitSet_printer.py | 3 ++- debug/printers/core/blocksList_printer.py | 11 +++++------ debug/printers/core/chain_printer.py | 6 +++--- debug/printers/core/prique_printer.py | 8 +++++++- debug/printers/core/tuple_printer.py | 11 +++-------- 7 files changed, 25 insertions(+), 35 deletions(-) diff --git a/debug/printers/core/array_printer.py b/debug/printers/core/array_printer.py index d4487f4..fa35ae9 100644 --- a/debug/printers/core/array_printer.py +++ b/debug/printers/core/array_printer.py @@ -20,12 +20,13 @@ def to_string(self): def children(self): size = int(call(self.val, "size")) - yield "size", size for i in range(0, size): v = call(self.val, "operator[]", f"{i}") if v.type.code == gdb.TYPE_CODE_REF: v = v.referenced_value() yield f"[{i}]", v + if gdb.parameter('print pretty') > 0: + yield "body", f"@{int(self.val["body"]):#x}" def display_hint(self): return "array" \ No newline at end of file diff --git a/debug/printers/core/autoPtr_printer.py b/debug/printers/core/autoPtr_printer.py index bd4f1ef..623fdfe 100644 --- a/debug/printers/core/autoPtr_printer.py +++ b/debug/printers/core/autoPtr_printer.py @@ -53,19 +53,7 @@ def children(self): if is_array_ptr(self.val): yield "array", f"@{ptr_val:#x}" else: - yield "pointer", f"@{ptr_val:#x}" if ptr_val != 0 else "nullptr" yield "object", ptr.dereference() - - ref_count = self.val['ref_count'] - loaded_ptr = call(ref_count, "operator*") - - try: - ref_count_base = loaded_ptr.dereference() - strong_refs_atomic = ref_count_base['strong_refs'] - weak_refs_atomic = ref_count_base['weak_refs'] - strong_refs = call(strong_refs_atomic, "operator*") - weak_refs = call(weak_refs_atomic, "operator*") - yield "strong_refs", to_int(strong_refs, U_INTEGER_SIZE) - yield "weak_refs", to_int(weak_refs, U_INTEGER_SIZE) - except gdb.error as e: - yield "ref_count_details", f"[cannot access: {e}]" \ No newline at end of file + if gdb.parameter('print pretty') > 0: + yield "ref count", self.val["ref_count"] + yield "alias ptr", self.val["alias_ptr"] \ No newline at end of file diff --git a/debug/printers/core/bitSet_printer.py b/debug/printers/core/bitSet_printer.py index 15f7335..6393b52 100644 --- a/debug/printers/core/bitSet_printer.py +++ b/debug/printers/core/bitSet_printer.py @@ -21,9 +21,10 @@ def to_string(self): def children(self): size = int(call(self.val, "size")) - yield "size", size for i in range(0, size): yield f"[{i}]", call(self.val, "get", f"{i}") + if gdb.parameter('print pretty') > 0: + yield "map", self.val["map"] def display_hint(self): return "array" \ No newline at end of file diff --git a/debug/printers/core/blocksList_printer.py b/debug/printers/core/blocksList_printer.py index 1695e5d..d5563d7 100644 --- a/debug/printers/core/blocksList_printer.py +++ b/debug/printers/core/blocksList_printer.py @@ -21,17 +21,16 @@ def to_string(self): def children(self): size = int(call(self.val, "size")) - yield "size", size for i in range(0, size): v = call(self.val, "operator[]", f"{i}") if v.type.code == gdb.TYPE_CODE_REF: v = v.referenced_value() yield f"[{i}]", v - - yield "first", self.val["first_"] - yield "last", self.val["last_"] - yield "first block", self.val["first_block"] - yield "last block", self.val["last_block"] + if gdb.parameter('print pretty') > 0: + yield "first", self.val["first_"] + yield "last", self.val["last_"] + yield "first block", self.val["first_block"] + yield "last block", self.val["last_block"] def display_hint(self): return "array" \ No newline at end of file diff --git a/debug/printers/core/chain_printer.py b/debug/printers/core/chain_printer.py index 1b63bb4..4b3eed3 100644 --- a/debug/printers/core/chain_printer.py +++ b/debug/printers/core/chain_printer.py @@ -20,11 +20,11 @@ def to_string(self): def children(self): size = int(call(self.val, "size")) - yield "size", size p = self.val["begin_"] for i in range(0, size): node = p.dereference() yield f"[{i}]", node["data_"] p = node["next"] - yield "begin", self.val["begin_"] - yield "end", self.val["end_"] \ No newline at end of file + if gdb.parameter('print pretty') > 0: + yield "begin", self.val["begin_"] + yield "end", self.val["end_"] \ No newline at end of file diff --git a/debug/printers/core/prique_printer.py b/debug/printers/core/prique_printer.py index a125f5d..4b95bf6 100644 --- a/debug/printers/core/prique_printer.py +++ b/debug/printers/core/prique_printer.py @@ -11,4 +11,10 @@ def __init__(self, val): super().__init__(val) def class_name(self): - return "original::prique" \ No newline at end of file + return "original::prique" + + def children(self): + for _, e in enumerate(super().children()): + yield e + if gdb.parameter('print pretty') > 0: + yield "compare", self.val["compare_"] \ No newline at end of file diff --git a/debug/printers/core/tuple_printer.py b/debug/printers/core/tuple_printer.py index e862893..88c1fff 100644 --- a/debug/printers/core/tuple_printer.py +++ b/debug/printers/core/tuple_printer.py @@ -31,21 +31,16 @@ def to_string(self): def children(self): elems = self.val['elems'] - elems_list = [] current = elems index = 0 while True: try: elem = current['cur_elem'] - elems_list.append(elem) - current = current['next'] + yield f"[{index}]", elem index += 1 + current = current['next'] except gdb.error: break - yield "size", index - for i, e in enumerate(elems_list): - yield f"[{i}]", e - def display_hint(self): - return None \ No newline at end of file + return "array" \ No newline at end of file From 5f4de23faf955bb1ec52fca01ad7e5c1bc89eb7a Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 14:34:11 +0800 Subject: [PATCH 74/81] feat: Add printer for hashSet and hashMap --- debug/printers/core/hashMap_printer.py | 24 +++++++++++++++ debug/printers/core/hashSet_printer.py | 23 ++++++++++++++ debug/printers/core/hashTable_printer.py | 39 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 debug/printers/core/hashMap_printer.py create mode 100644 debug/printers/core/hashSet_printer.py create mode 100644 debug/printers/core/hashTable_printer.py diff --git a/debug/printers/core/hashMap_printer.py b/debug/printers/core/hashMap_printer.py new file mode 100644 index 0000000..7dc608f --- /dev/null +++ b/debug/printers/core/hashMap_printer.py @@ -0,0 +1,24 @@ +# debug/printers/core/hashMap_printer.py + +import gdb +from hashTable_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::hashMap""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::hashMap" + + def children(self): + for i, cp in enumerate(self.elem()): + yield f"[{i}].key", cp[0] + yield f"[{i}].value", cp[1] + if gdb.parameter('print pretty') > 0: + yield "buckets", self.val["buckets"] + + def display_hint(self): + return "map" \ No newline at end of file diff --git a/debug/printers/core/hashSet_printer.py b/debug/printers/core/hashSet_printer.py new file mode 100644 index 0000000..1c97e88 --- /dev/null +++ b/debug/printers/core/hashSet_printer.py @@ -0,0 +1,23 @@ +# debug/printers/core/hashSet_printer.py + +import gdb +from hashTable_printer import PrinterBase as Base + + +class Printer(Base): + """Pretty printer for original::hashSet""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::hashSet" + + def children(self): + for i, cp in enumerate(self.elem()): + yield f"[{i}]", cp[0] + if gdb.parameter('print pretty') > 0: + yield "buckets", self.val["buckets"] + + def display_hint(self): + return "array" diff --git a/debug/printers/core/hashTable_printer.py b/debug/printers/core/hashTable_printer.py new file mode 100644 index 0000000..fb8958c --- /dev/null +++ b/debug/printers/core/hashTable_printer.py @@ -0,0 +1,39 @@ +# debug/printers/core/hashTable_printer.py + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class PrinterBase: + """Pretty printer for derived classes of hashTable in original""" + + def __init__(self, val): + self.val = val + + def class_name(self): + return "original::hashTable" + + def to_string(self): + size = int(call(self.val, "size")) + return f"{self.class_name()}(size={size}, {addr_str(self.val)})" + + def elem(self): + size = int(call(self.val, "size")) + if size == 0: + return + cnt = 0 + buckets = self.val['buckets'] + length = int(call(buckets, "size")) + for i in range(length): + p = call(buckets, "operator[]", f"{i}") + while p != 0: + node = p.dereference() + cp = node["data_"] + yield cp["first_"], cp["second_"] + cnt += 1 + if cnt == size: + return + p = node["next_"] From dac53a730b77f02318ad5b66da132e079d59e86c Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 21:27:09 +0800 Subject: [PATCH 75/81] fix: Properly handle reference types --- debug/printers/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debug/printers/utils.py b/debug/printers/utils.py index 0157052..f8e7da2 100644 --- a/debug/printers/utils.py +++ b/debug/printers/utils.py @@ -26,6 +26,8 @@ def type_name(obj): def call(obj, method_name, *args): try: + if obj.type.code == gdb.TYPE_CODE_REF: + obj = obj.referenced_value() args_str = ', '.join(str(arg) for arg in args) addr = address(obj) expr = f'(({type_name(obj)}*)({addr}))->{method_name}({args_str})' From 9f6df6ba1b96f40d170f7d41b784d88d2c2aeac1 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 21:27:49 +0800 Subject: [PATCH 76/81] feat: Add pretty format for treeSet and treeMap --- debug/printers/core/RBTree_printer.py | 79 ++++++++++++++++++++++++++ debug/printers/core/treeMap_printer.py | 31 ++++++++++ debug/printers/core/treeSet_printer.py | 30 ++++++++++ 3 files changed, 140 insertions(+) create mode 100644 debug/printers/core/RBTree_printer.py create mode 100644 debug/printers/core/treeMap_printer.py create mode 100644 debug/printers/core/treeSet_printer.py diff --git a/debug/printers/core/RBTree_printer.py b/debug/printers/core/RBTree_printer.py new file mode 100644 index 0000000..8db4a04 --- /dev/null +++ b/debug/printers/core/RBTree_printer.py @@ -0,0 +1,79 @@ +# debug/printers/core/RBTree_printer.py + +import gdb +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +def get_successor_node(ptr): + if ptr == 0: + return 0 + node = ptr.dereference() + if node["right_"] != 0: + ptr = node["right_"] + node = ptr.dereference() + while node["left_"] != 0: + ptr = node["left_"] + node = ptr.dereference() + return ptr + + node = ptr.dereference() + ptr_parent = node["parent_"] + node = ptr_parent.dereference() + + while ptr_parent != 0 and ptr == node["right_"]: + ptr = ptr_parent + node = ptr_parent.dereference() + ptr_parent = node["parent_"] + return ptr_parent + + +class PrinterBase: + """Pretty printer for derived classes of RBTree in original""" + + def __init__(self, val): + self.val = val + + def class_name(self): + return "original::RBTree" + + def to_string(self): + size = int(call(self.val, "size")) + return f"{self.class_name()}(size={size}, {addr_str(self.val)})" + + def get_min_node(self): + p = self.val["root_"] + if p == 0: + return p + node = p.dereference() + while node["left_"] != 0: + p = node["left_"] + node = p.dereference() + return p + + def get_max_node(self): + p = self.val["root_"] + if p == 0: + return p + node = p.dereference() + while node["right_"] != 0: + p = node["right_"] + node = p.dereference() + return p + + def elem(self): + if self.val["root_"] == 0: + return + cur = self.get_min_node() + end = self.get_max_node() + while cur != end: + node = cur.dereference() + cp = node["data_"] + yield cp["first_"], cp["second_"] + cur = get_successor_node(cur) + if end != 0: + node = end.dereference() + cp = node["data_"] + yield cp["first_"], cp["second_"] diff --git a/debug/printers/core/treeMap_printer.py b/debug/printers/core/treeMap_printer.py new file mode 100644 index 0000000..346f70c --- /dev/null +++ b/debug/printers/core/treeMap_printer.py @@ -0,0 +1,31 @@ +# debug/printers/core/treeMap_printer.py + +import gdb +from RBTree_printer import PrinterBase as Base +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer(Base): + """Pretty printer for original::treeMap""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::treeMap" + + def children(self): + for i, cp in enumerate(self.elem()): + yield f"[{i}].key", cp[0] + yield f"[{i}].value", cp[1] + if gdb.parameter('print pretty') > 0: + addr_root = addr_str(self.val["root_"]) + addr_cmp = addr_str(self.val["compare_"]) + yield "root", f"{addr_root}" + yield "compare", f"{addr_cmp}" + + def display_hint(self): + return "map" \ No newline at end of file diff --git a/debug/printers/core/treeSet_printer.py b/debug/printers/core/treeSet_printer.py new file mode 100644 index 0000000..df2bbd8 --- /dev/null +++ b/debug/printers/core/treeSet_printer.py @@ -0,0 +1,30 @@ +# debug/printers/core/treeSet_printer.py + +import gdb +from RBTree_printer import PrinterBase as Base +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from utils import * + + +class Printer(Base): + """Pretty printer for original::treeSet""" + + def __init__(self, val): + super().__init__(val) + + def class_name(self): + return "original::treeSet" + + def children(self): + for i, cp in enumerate(self.elem()): + yield f"[{i}]", cp[0] + if gdb.parameter('print pretty') > 0: + addr_root = addr_str(self.val["root_"]) + addr_cmp = addr_str(self.val["compare_"]) + yield "root", f"{addr_root}" + yield "compare", f"{addr_cmp}" + + def display_hint(self): + return "array" \ No newline at end of file From 3279236ce6c3aa4d0b9a90ddfb69899ee8870be9 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 21:29:07 +0800 Subject: [PATCH 77/81] refactor: Optimize the output of the children/to_string methods --- debug/printers/core/array_printer.py | 3 ++- debug/printers/core/vector_printer.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/debug/printers/core/array_printer.py b/debug/printers/core/array_printer.py index fa35ae9..5a85c91 100644 --- a/debug/printers/core/array_printer.py +++ b/debug/printers/core/array_printer.py @@ -26,7 +26,8 @@ def children(self): v = v.referenced_value() yield f"[{i}]", v if gdb.parameter('print pretty') > 0: - yield "body", f"@{int(self.val["body"]):#x}" + addr = addr_str(self.val["body"]) + yield "body", f"{addr}" def display_hint(self): return "array" \ No newline at end of file diff --git a/debug/printers/core/vector_printer.py b/debug/printers/core/vector_printer.py index dcc2921..cf69b0f 100644 --- a/debug/printers/core/vector_printer.py +++ b/debug/printers/core/vector_printer.py @@ -15,11 +15,12 @@ def __init__(self, val): self.val = val def to_string(self): - return f"original::vector({addr_str(self.val)})" + size = int(call(self.val, "size")) + capacity = self.val["max_size"] + return f"original::vector(size={size}, cap={capacity}, {addr_str(self.val)})" def children(self): size = int(call(self.val, "size")) - yield "size", size for i in range(0, size): v = call(self.val, "operator[]", f"{i}") if v.type.code == gdb.TYPE_CODE_REF: From 3ed6372b9f4222df507072738ab7682ea8da5d5d Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 14 Oct 2025 22:44:33 +0800 Subject: [PATCH 78/81] fix: Fix the issue where ctest cannot find the tests --- CMakeLists.txt | 2 ++ test/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7c48a0..f2168b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,5 +78,7 @@ add_subdirectory(debug) option(BUILD_TESTING "Build the testing directories" ON) if (BUILD_TESTING) + include(CTest) + enable_testing() add_subdirectory(test) endif () \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8153c15..8c06175 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,5 @@ # test/CMakeLists.txt -include(CTest) if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") From 21a8f0ae24fdd1d532365898d6f35189090fecb8 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Wed, 15 Oct 2025 00:22:01 +0800 Subject: [PATCH 79/81] fix: Add missing headers --- src/vibrant/atomic.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vibrant/atomic.h b/src/vibrant/atomic.h index ce8bf75..bebfd3b 100644 --- a/src/vibrant/atomic.h +++ b/src/vibrant/atomic.h @@ -1,15 +1,19 @@ #ifndef ORIGINAL_ATOMIC_H #define ORIGINAL_ATOMIC_H +#include "config.h" + #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG #include #elif ORIGINAL_COMPILER_MSVC +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include #endif - -#include #include "optional.h" -#include "config.h" #include "mutex.h" namespace original { From 63fdd4c0c0e18dedbe2477e9af0343ddc0715013 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Wed, 15 Oct 2025 00:22:43 +0800 Subject: [PATCH 80/81] refactor: Change trigger condition of ci test --- .github/workflows/basic-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/basic-tests.yml b/.github/workflows/basic-tests.yml index cd7de7d..074599e 100644 --- a/.github/workflows/basic-tests.yml +++ b/.github/workflows/basic-tests.yml @@ -3,7 +3,7 @@ name: Test Branch CI - Basic Tests on: - push: + pull_request: branches: [ test ] jobs: From 8782f521f8baf3daf850962c9c57edad563ad896 Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Wed, 15 Oct 2025 00:23:21 +0800 Subject: [PATCH 81/81] refactor: Add compiler version min require --- CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2168b0..54f0e5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,38 @@ set(ORIGINAL_VERSION 0.1.5) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_EXTENSIONS OFF) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) + message(FATAL_ERROR "GCC version too old. Minimum required: 13.0. Current: ${CMAKE_CXX_COMPILER_VERSION}") + else() + message(STATUS "GCC version: ${CMAKE_CXX_COMPILER_VERSION} (>= 13.0 ✓)") + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20.0) + message(FATAL_ERROR "Clang version too old. Minimum required: 20.0. Current: ${CMAKE_CXX_COMPILER_VERSION}") + else() + message(STATUS "Clang version: ${CMAKE_CXX_COMPILER_VERSION} (>= 20.0 ✓)") + endif() +endif() +if(MSVC) + if(MSVC_VERSION LESS 1944) + message(FATAL_ERROR "MSVC version too old. Minimum required: 14.44.35207 (VS2022 17.10+). Current: ${MSVC_VERSION}") + else() + message(STATUS "MSVC version: ${MSVC_VERSION} (>= 14.44 ✓)") + endif() + set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION "10.0" CACHE STRING "Windows Target Platform Version") +endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-std=c++23" HAS_CXX23_FLAG) + if(NOT HAS_CXX23_FLAG) + message(WARNING "Compiler may not fully support C++23 standard") + endif() +endif() + if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (default Release)" FORCE) endif()