jbaldwin / libcoro

C++20 coroutine library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MSVC compiler warning

bjones1 opened this issue · comments

From the MSVC compiler:

D:\a\libcoro\libcoro\include\coro/when_all.hpp(447): warning C4033: 'coro::detail::make_when_all_task' must return a value 
[D:\a\libcoro\libcoro\build-release-cl\examples\coro_thread_pool.vcxproj]
D:\a\libcoro\libcoro\include\coro/when_all.hpp(447): message : Flowing off the end of a coroutine results in undefined behavior when
promise type 'coro::detail::when_all_task_promise<return_type>' does not declare 'return_void' [D:\a\libcoro\libcoro\build-release-cl\examples\coro_thread_pool.vcxproj]
          with
          [
              return_type=unsigned __int64 &&
          ]
D:\a\libcoro\libcoro\include\coro/when_all.hpp(475): message : see reference to function template instantiation
 'coro::detail::when_all_task<unsigned __int64 &&> coro::detail::make_when_all_task<coro::task<uint64_t>,unsigned __int64&&>
(awaitable)' being compiled [D:\a\libcoro\libcoro\build-release-cl\examples\coro_thread_pool.vcxproj]
          with
          [
              awaitable=coro::task<uint64_t>
          ]
D:\a\libcoro\libcoro\examples\coro_thread_pool.cpp(74): message : see reference to function template instantiation 
'coro::detail::when_all_ready_awaitable<std::vector<coro::detail::when_all_task<unsigned __int64 
&&>,std::allocator<coro::detail::when_all_task<unsigned __int64 &&>>>> 
coro::when_all<std::vector<coro::task<uint64_t>,std::allocator<coro::task<uint64_t>>>,coro::task<uint64_t>,unsigned __int64&&>
(range_type)' being compiled [D:\a\libcoro\libcoro\build-release-cl\examples\coro_thread_pool.vcxproj]
          with
          [
              range_type=std::vector<coro::task<uint64_t>,std::allocator<coro::task<uint64_t>>>
          ]

Unfortunately, I lack the C++ knowledge to fix this myself.

@a858438680. do you know how to fix this?

@a858438680. do you know how to fix this?

Yes, I know. Just don't use co_yield and change it to co_return and change some of the member functions in the promise type.

I tried to change this locally. But I can't tell why the author designed it this way. So I didn't create a pull request. You can ask him and if he thinks I'm right, I will create a PR.

@jbaldwin, are you open to a PR from @a858438680 which would fix this? Did you have any specific design goals in mind, or is s/he free to innovate?

Honestly I don't remember why I did it this way a few years ago, looking at the code using co yield shouldn't be necessary. I'm definitely open to a PR to clean this up.

Honestly I don't remember why I did it this way a few years ago, looking at the code using co yield shouldn't be necessary. I'm definitely open to a PR to clean this up.

Here is the thing, I'm also glad to create a PR but I also thinks that the api of when_all is not proper, co_await a when_all_task should return the value of all tasks rather than get a container of some handles.

But if you think that it is ok now and does not want a broken change, I will create a PR which just cleans the warning. Otherwise, if you think that adding a new api or changing the behavior of co_await when_all is acceptable, please tell me you your opinion.

The original intent behind the coro::when_all api is so that you can compose it with coro::sync_wait as well as co_await it within a coroutine. I realize now typing this out there is no test for coro::when_all within the test_when_all.cpp file so I'm going to add one. #197

Can you propose an API that would return the values directly that would work in both situations? Or would it require two implementations, one coro::when_all to work outside a coroutine context and another to work inside coroutine contexts? The former would mean all instances of coro::sync_wait(coro::when_all(...awaitables...)) would become coro::when_all(...awaitables...). If you have a way to make it work both ways without duplicating it I'd love to see that.

How would you handle multiple exceptions being thrown? Right now you get each one upon calling each output task's return_value() and can handle them individually, I think you'd need a std::variant<return_type, std::exception> type result to capture each one appropriately for the user.

I'm kind of thinking something new coro::when_all_values(awaitable...) -> coro::generator<result<T, E>>, perhaps two APIs isn't the worst.

I've implemented a temporary solution to address the build warning and have also raised a pull request for it. @jbaldwin , when you have a moment, could you please take a look and provide your feedback?

Thanks for taking the time to write this up to fix the warning.