Skip to content
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

Extend collect any #371

Merged
merged 20 commits into from
Mar 15, 2024
Merged

Extend collect any #371

merged 20 commits into from
Mar 15, 2024

Conversation

qicosmos
Copy link
Collaborator

@qicosmos qicosmos commented Mar 8, 2024

Why

extend collectAny with callback, similar with go/kotlin select coroutine function.

What is changing

add two new collectAny methods

Example

collectAny with variadic callback functions:

    auto test0 = []() -> Lazy<Unit> { co_return Unit{}; };
    auto test1 = []() -> Lazy<int> { co_return 42; };
    auto test2 = [](int val) -> Lazy<std::string> {
        co_return std::to_string(val);
    };

    int call_count = 0;
    index =
        syncAwait(collectAny(std::pair{test0(), [&](auto) { call_count++; }},
                             std::pair{test1(),
                                       [&](auto val) {
                                           call_count++;
                                           EXPECT_EQ(val.value(), 42);
                                       }},
                             std::pair{test2(42), [&](auto val) {
                                           call_count++;
                                           EXPECT_EQ("42", val.value());
                                       }}));
    EXPECT_EQ(1, call_count);

collectAny with vector callback function:

    auto test0 = []() -> Lazy<int> { co_return 41; };
    auto test1 = []() -> Lazy<int> { co_return 42; };

    std::vector<Lazy<int>> input;
    input.push_back(test0());
    input.push_back(test1());

    syncAwait(collectAny(std::move(input), [](size_t index, Try<int> val) {
        if (index == 0) {
            EXPECT_EQ(val.value(), 41);
        } else {
            EXPECT_EQ(val.value(), 42);
        }
    }));

Comment on lines 516 to 520
async_simple::coro::Lazy<size_t> operator()(auto&&... lazy) {
auto result = co_await collectAny(std::move(lazy)...);

tupleSwitch(result.index(), _callback_tuple, result);
co_return result.index();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to avoid adding layers in implementing fundamental functions by new co_await. It may results new allocations/deallocations, which may be a performance concern.

Comment on lines 1142 to 1156
index = syncAwait(collectAny(std::pair{test3().via(&e1),
[&](auto val) {
test_value = val.value();
EXPECT_EQ(42, test_value);
}},
std::pair{test4(41).via(&e1), [&](auto val) {
test_value = val.value();
EXPECT_EQ(41, test_value);
}}));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be better if we can avoid writing std::pair and try to use {, }. It may be possible to construct a pair from the initializer list.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe it's impossible: https://stackoverflow.com/questions/65071836/template-argument-deduction-for-implicit-pair

can't use std::initializer_list to avoid std::pair with brace initialize.

another reason, can't use std::initializer_list because it requires types are the same, not variadic template.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

Copy link
Collaborator

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also we need to add documents for this.

std::make_tuple(std::move(std::get<1>(std::get<I>(tuple)))...));
}(std::make_index_sequence<sizeof...(Ts)>());

auto result = co_await std::move(lazy_pair.first);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still introduces new coroutines, which may be a performance concern. Let's try to avoid the new creation of coroutines as much as possible.

Comment on lines 1142 to 1156
index = syncAwait(collectAny(std::pair{test3().via(&e1),
[&](auto val) {
test_value = val.value();
EXPECT_EQ(42, test_value);
}},
std::pair{test4(41).via(&e1), [&](auto val) {
test_value = val.value();
EXPECT_EQ(41, test_value);
}}));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

Copy link
Collaborator

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to update the document for such new features.

.clang-format Outdated
Comment on lines 103 to 104
Language: ObjC
DisableFormat: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be related.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unrelated change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must not be correct. There is nothing related to ObjC.

return detail::collectAnyImpl(std::move(input));
typename IAlloc = std::allocator<LazyType<T>>, typename... Function>
inline auto collectAny(std::vector<LazyType<T>, IAlloc>&& input,
Function... func) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the Function is variadic? There should be only one function with the vector version.

Copy link
Collaborator Author

@qicosmos qicosmos Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to reuse code, the original vector version no callback function, if user don't pass a callback function, the code go back to original version, otherwise go to callback version

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel better with offering an overload here to make things explciitly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, remove the variadic template, use a template parameter: Callback, the default Callback type is Unit, and the
default Callback member variable can be optimized by compiler via [[no_unique_address]].

@@ -83,18 +83,22 @@ struct CollectAnyResult {
#endif
};

template <typename LazyType, typename InAlloc>
template <typename LazyType, typename InAlloc, typename... Function>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <typename LazyType, typename InAlloc, typename... Function>
template <typename LazyType, typename InAlloc, typename... Callback>

Let's rename Function to Callback. Ditto for the following patch.

async_simple/coro/Collect.h Show resolved Hide resolved

auto await_resume() {
assert(_result != nullptr);
return std::move(_result->value());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we don't return value with callbacks for vectors but returning here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variadic version no need index, because the sequence is the index. the index for vector version.

Copy link
Collaborator Author

@qicosmos qicosmos Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vector version return index is good, unify the return type of vector and variadic version is better.

Copy link
Collaborator

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document this

.clang-format Outdated
Comment on lines 103 to 104
Language: ObjC
DisableFormat: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unrelated change.

EXPECT_STREQ("testCollectAllVariadic", v_try_string.value().c_str());

CHECK_EXECUTOR(&e1);
// TEST_F(LazyTest, testCollectAllVariadic) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the tests got commented out?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for test, will revert.

@@ -1,4 +1,5 @@
file(GLOB coro_test_src "*.cpp")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/bigobj>")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be related to this patch. Please remove the unrelated change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will create a new PR to add this compile option for msvc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in this PR: #375

- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do one thing in one patch. Please move this to other PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, when test passed will create a new pr to upgrade clang for conan.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR upgrade clang version: #373

@qicosmos qicosmos force-pushed the extend_collectAny branch from b29aaf0 to 5aaeab6 Compare March 14, 2024 09:28
@qicosmos qicosmos force-pushed the extend_collectAny branch from 5aaeab6 to 3de9c8e Compare March 15, 2024 03:10
@qicosmos qicosmos merged commit 6be48e7 into alibaba:main Mar 15, 2024
14 checks passed
@qicosmos qicosmos deleted the extend_collectAny branch March 15, 2024 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants