Skip to content

Commit

Permalink
Update CI compiler matrix
Browse files Browse the repository at this point in the history
Update the compiler matrix:
 - add Clang 18
 - add MSVC 2022
 - remove MSVC 2019 C++17 since it's been broken forever
 - remove the configuration settings that ignore experimental failures

Also update `spawn_future.hpp` to keep the tests passing with MSVC 2022.
  • Loading branch information
ispeters committed Sep 2, 2024
1 parent 1e8c127 commit 297be31
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 51 deletions.
51 changes: 36 additions & 15 deletions .github/workflows/libunifex-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,22 @@ jobs:
cc: "clang-17", cxx: "clang++-17",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20 -D \"CMAKE_CXX_FLAGS:STRING=-fsanitize=address -fno-omit-frame-pointer\""
}
- {
name: "Linux Clang 18 Debug (C++20)", artifact: "Linux.tar.xz",
os: ubuntu-20.04,
io_sys: io_uring,
build_type: Debug,
cc: "clang-18", cxx: "clang++-18",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20 -D \"CMAKE_CXX_FLAGS:STRING=-fsanitize=address -fno-omit-frame-pointer\""
}
- {
name: "Linux Clang 18 Optimised (C++20)", artifact: "Linux.tar.xz",
os: ubuntu-20.04,
io_sys: io_uring,
build_type: RelWithDebInfo,
cc: "clang-18", cxx: "clang++-18",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20 -D \"CMAKE_CXX_FLAGS:STRING=-fsanitize=address -fno-omit-frame-pointer\""
}
- {
name: "macOS GCC Debug (C++17)", artifact: "macOS.tar.xz",
os: macos-latest,
Expand Down Expand Up @@ -367,37 +383,35 @@ jobs:
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20 -D \"CMAKE_CXX_FLAGS:STRING=-fsanitize=address -fno-omit-frame-pointer\""
}
- {
name: "Windows MSVC 2019 Debug (C++17)", artifact: "Windows-MSVC.tar.xz",
name: "Windows MSVC 2019 Debug (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2019,
build_type: Debug,
cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=17",
experimental: true
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20",
}
- {
name: "Windows MSVC 2019 Optimised (C++17)", artifact: "Windows-MSVC.tar.xz",
name: "Windows MSVC 2019 Optimised (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2019,
build_type: RelWithDebInfo,
cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=17",
experimental: true
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20",
}
- {
name: "Windows MSVC 2019 Debug (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2019,
name: "Windows MSVC 2022 Debug (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2022,
build_type: Debug,
cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20",
}
- {
name: "Windows MSVC 2019 Optimised (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2019,
name: "Windows MSVC 2022 Optimised (C++20)", artifact: "Windows-MSVC.tar.xz",
os: windows-2022,
build_type: RelWithDebInfo,
cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
cmake_args: "-D CMAKE_CXX_STANDARD:STRING=20",
}

Expand Down Expand Up @@ -506,6 +520,16 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 17
- name: Install Clang 18
id: install_clang_18
if: startsWith(matrix.config.os, 'ubuntu') && ( matrix.config.cxx == 'clang++-18' )
shell: bash
working-directory: ${{ env.HOME }}
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18
- name: Install GCC 11
id: install_gcc_11
if: startsWith(matrix.config.os, 'ubuntu') && ( matrix.config.cxx == 'g++-11' )
Expand Down Expand Up @@ -599,7 +623,6 @@ jobs:
- name: Build
shell: cmake -P {0}
continue-on-error: ${{ matrix.config.experimental || false }}
run: |
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
Expand Down Expand Up @@ -628,7 +651,6 @@ jobs:
- name: Run tests
shell: cmake -P {0}
continue-on-error: ${{ matrix.config.experimental || false }}
run: |
include(ProcessorCount)
ProcessorCount(N)
Expand All @@ -646,7 +668,6 @@ jobs:
- name: Install
shell: cmake -P {0}
continue-on-error: ${{ matrix.config.experimental || false }}
run: |
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
Expand Down
75 changes: 39 additions & 36 deletions include/unifex/spawn_future.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
Expand Down Expand Up @@ -954,54 +954,57 @@ struct _spawn_future_fn {
alloc_traits_t::construct(opAlloc, op, opAlloc);

// the next two steps might throw and we have to destroy op if one of them
// does throw so set up a scope_guard that will do that for us;
// conveniently, the deleter() static method does exactly the right thing
scope_guard cleanUp = [op]() noexcept {
// does throw; we used to use a scope_guard here but it triggers a
// miscompilation bug in VS 2022's MSVC that isn't triggered with a
// traditional try-catch block
UNIFEX_TRY {
using future_t = future_for<remove_cvref_t<Sender>, Scope, byte_alloc_t>;

// construct the future that we'll hand back to the caller; this is fairly
// likely to be noexcept since it's not much more than a Sender
// construction but it depends on the implementation of nest() for scope
// so it might throw
future_t future{scope, op};

// now finally construct the spawned operation, which might throw
op->init_operation(static_cast<Sender&&>(sender), scope, op);

// now that everything is wired together there are no more exception
// concerns from here

// start the spawned operation
start(*op);

// ideally, the compiler performs NRVO and constructs this future in-place
// at the call site but future<>'s move constructor is noexcept so even if
// there's an actual move here, there's still no chance of an exception
return future;
}
UNIFEX_CATCH(...) {
// Constructing the future is *almost* no-throw--only the call to nest()
// might throw--so the future will invoke drop() on the operation (moving
// it from init to complete) as part of its destructor before this code
// runs.
op_t::deleter(op, _future_state::complete);
};

using future_t = future_for<remove_cvref_t<Sender>, Scope, byte_alloc_t>;

// construct the future that we'll hand back to the caller; this is fairly
// likely to be noexcept since it's not much more than a Sender construction
// but it depends on the implementation of nest() for scope so it might
// throw
future_t future{scope, op};

// now finally construct the spawned operation, which might throw
op->init_operation(static_cast<Sender&&>(sender), scope, op);

// now that everything is wired together there are no more exception
// concerns
cleanUp.release();

// start the spawned operation
start(*op);

// ideally, the compiler performs NRVO and constructs this future in-place
// at the call site but future<>'s move constructor is noexcept so even if
// there's an actual move here, there's still no chance of an exception
return future;
throw;
}
}

template <typename Scope, typename Alloc = std::allocator<std::byte>>
constexpr auto operator()(Scope& scope, const Alloc& alloc = {}) const
noexcept(
std::is_nothrow_invocable_v<tag_t<bind_back>, deref, Scope*, const Alloc&>)
-> std::enable_if_t<
is_allocator_v<Alloc>,
bind_back_result_t<deref, Scope*, const Alloc&>>;
constexpr auto
operator()(Scope& scope, const Alloc& alloc = {}) const noexcept(
std::
is_nothrow_invocable_v<tag_t<bind_back>, deref, Scope*, const Alloc&>)
-> std::enable_if_t<
is_allocator_v<Alloc>,
bind_back_result_t<deref, Scope*, const Alloc&>>;
};

struct _spawn_future_fn::deref final {
template <typename Sender, typename Scope, typename Alloc>
auto operator()(Sender&& sender, Scope* scope, const Alloc& alloc) const
-> decltype(
_spawn_future_fn{}(static_cast<Sender&&>(sender), *scope, alloc)) {
-> decltype(_spawn_future_fn{}(
static_cast<Sender&&>(sender), *scope, alloc)) {
return _spawn_future_fn{}(static_cast<Sender&&>(sender), *scope, alloc);
}
};
Expand Down

0 comments on commit 297be31

Please sign in to comment.