-
Notifications
You must be signed in to change notification settings - Fork 470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GCC 10.1 support #158
base: master
Are you sure you want to change the base?
GCC 10.1 support #158
Conversation
Starting with GCC 10.1, GCC/libstdc++ supports coroutines, but includes them in their final location in <coroutine>. This commit generalizes the location of the header, and the name of the types (either in the std or std::experimental namespace), so that both the current Clang/MSVC and the GCC approach can be supported. This should also guarantee that both current and later Clang/MSVC releases will be supported by the library.
While clang uses the -fcoroutines-ts flag to add support for the Coroutines TS, GCC uses the -fcoroutines flag. This commit refactors the cmake finder to support both.
* Included missing headers * Disabled a testcase for GCC that uses a syntax not supported by GCC10.1 * Reordered a class so GCC is able to find a data member
After these changes, there's one failure remaining with GCC 10.1, where it doesn't call a destructor for an object, and calls another later than it should. Other tests required workarounds for bugs in the GCC coroutine implementation, but were possible to fix with minor code modifications.
Great job! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much for the PR!
CMake and GCC support have been requested by several people.
My apologies for taking so long to review.
A few minor things to address:
- Some accidental changes of
std::experimental::filesystem
tocppcoro::filesystem
(which will break the Windows builds) - Missing reexport of
std::noop_coroutine()
- There is some debug spam still in
test/counted.hpp
- I'm not sure that some of the workarounds to get tests passing with GCC 10.1 are worthwhile.
GCC 10.1 coroutines support was quite broken.
I'd probably recommend requiring GCC 10.2 as a minimum compiler version for use with cppcoro.
Also, it would be good to hook up the CI configs to exercise the CMake builds to avoid regressions.
This can be deferred to a later PR though.
|
||
find_package_handle_standard_args(CppcoroCoroutines | ||
REQUIRED_VARS Coroutines_LIBRARY_SUPPORT Coroutines_COMPILER_SUPPORT | ||
FAIL_MESSAGE "Verify that the compiler and the standard library both support the Coroutines TS") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Maybe reword to also be inclusive of C++20 coroutines, not just Coroutines TS?
"... both support either C++20 coroutines or the Coroutines TS"
|
||
namespace cppcoro { | ||
template<typename Promise=void> | ||
using coroutine_handle = std::coroutine_handle<Promise>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also one place that makes use of std::experimental::noop_coroutine()
(round_robin_scheduler.hpp
) which also needs to be made available if it's provided by the platform headers.
It should be supported by all <coroutine>
headers (since that's required by the C++20 spec).
However, compilers that just implemented the coroutines TS may not have it (e.g. early versions of clang and all MSVC versions).
We may need some kind of detection/macro to enable this (or maybe we can use feature-macros to detect it?)
#include <experimental/coroutine> | ||
#include <cppcoro/coroutine.hpp> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like this include is needed.
Remove it instead?
#include <experimental/coroutine> | ||
#include <cppcoro/coroutine.hpp> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly here, include seems to be unused. Maybe just remove this include?
@@ -61,7 +61,7 @@ namespace cppcoro | |||
public: | |||
round_robin_scheduler() noexcept | |||
: m_index(0) | |||
, m_noop(std::experimental::noop_coroutine()) | |||
, m_noop(cppcoro::noop_coroutine()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The noop_coroutine()
function has not been exported from cppcoro
yet.
// GCC 10.1 workaround: "co_yield start++ always returns the same value, resulting in an infinite loop | ||
// ((++start)-1) seems to have the same issue, while ++start works, but breaks the test | ||
start++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GCC 10.1 had a large number of coroutine bugs. I wouldn't recommend it for any coroutine code in production.
This issue should hopefully have been fixed in 10.2, although I'm not sure whether this particular issue was reported.
Possibly related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95017 or https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95599 ?
// GCC 10.1 workaround: GCC doesn't generate any code for a for loop with only a co_await in it | ||
[](){}(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fixed in GCC 10.2.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95017
// GCC 10.1 performs 2 copies | ||
CHECK(counted::copy_construction_count >= 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fixed in GCC 10.2
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95350
@@ -112,6 +112,9 @@ TEST_CASE("when_all() with all task types") | |||
|
|||
CHECK(a == "foo"); | |||
CHECK(b.id == 0); | |||
// GCC 10.1 fails this check: at this point there are 3 objects alive | |||
// * One will be destructed later | |||
// * One object is completely leaked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I wonder why this one is failing.
There were a few destructor-related bugs I found in 10.1 most of which should be fixed in 10.2.
Have you tested this with 10.2 to see if it passes?
namespace fs = std::experimental::filesystem; | ||
namespace fs = cppcoro::filesystem; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidental search+replace change?
I couldn't see any changes that would have reexported std::experimental::filesystem
under cppcoro
.
Also see other headers: file.hpp/cpp
, read_write_file.hpp/cpp
, read_only_file.hpp/cpp
, write_only_file.hpp/cpp
I've done similar CMake+GCC support for local experiments and implemented several things differently, not quite clean though. include(GNUInstallDirs)
# install headers
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/cppcoro
TYPE INCLUDE
)
# install binary
install(TARGETS cppcoro_lib
EXPORT coro
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# install config for find_package()
install(EXPORT coro
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cppcoro
NAMESPACE cppcoro::
FILE cppcoroConfig.cmake
)
# generate export file
export(EXPORT coro
NAMESPACE cppcoro::
FILE cppcoroExport.cmake
) It's usually good to set default CMAKE_BUILD_TYPE to Release. People then can use canonical CMake installation |
Just want to say that I'm excited about this. |
@OleksandrKvl the cmake files are from #110, I didn't change those. And I'm not sure if defaulting to release is a good idea, as that would effect multi-buildtype IDE setups also (like visual studio or xcode). If a projects wants to set a default build type correctly, it usually requires several conditions (don't do anything if using a multi config generator ; use debug if the .git directory is present ; use relwithdebinfo otherwise) @lewissbaker I'll updat my PR based on your comments, but do you have plans about #110? As currently this PR includes that commit too. |
I've added some comments to #110. @dutow Would it be possible to separate this PR out into just the code-changes needed for GCC support and not have it build upon the CMake changes, so that they can be merged independently? |
@lewissbaker Then we don't have a build system I'm actually familiar with. Cake seems to be a custom tool written by you, and the cake script currently forces clang on linux/osx. Seems like adding gcc there would require more changes than the cmake script (adding a config to choose the compiler, then refactoring the entire linux/darwin section to handle both clang and gcc) Also, then we'll have to add d99be58 to the cmake pullrequest instead. |
This pull requests adds GCC support on top of @mmha's CMake pull request.
I cherry picked his commit to the current master branch for this, I will rebase my pull request once that PR is merged.
I opened this for now only so my changes can be reviewed.
As I explained in my last commit message GCC 10.1 seems to have remaining bugs causing test failures. I found workarounds for some of them, but I had to completely remove one testcase for GCC (not supported syntax), and leave a test failure as is (missing destructor call). Otherwise the library seems to be working.