File: co-await-syntax-11.C

package info (click to toggle)
gcc-arm-none-eabi 15%3A12.2.rel1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 959,712 kB
  • sloc: cpp: 3,275,382; ansic: 2,061,766; ada: 840,956; f90: 208,513; makefile: 76,132; asm: 73,433; xml: 50,448; exp: 34,146; sh: 32,436; objc: 15,637; fortran: 14,012; python: 11,991; pascal: 6,787; awk: 4,779; perl: 3,054; yacc: 338; ml: 285; lex: 201; haskell: 122
file content (205 lines) | stat: -rw-r--r-- 6,750 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//  { dg-additional-options "-std=c++17 -w" }

#include <utility>
#include <type_traits>
#include <tuple>
#include <functional>
#include <coroutine>

struct any {
  template <typename T> any(T &&) noexcept;
};

template <typename T>
auto get_awaiter_impl(T &&value, int) noexcept
    -> decltype(static_cast<T &&>(value).operator co_await()) {
  return static_cast<T &&>(value).operator co_await();
}
template <typename T, int = 0>
T &&get_awaiter_impl(T &&value, any) noexcept;
template <typename T>
auto get_awaiter(T &&value) noexcept
    -> decltype(get_awaiter_impl(static_cast<T &&>(value), 123)) {
  return get_awaiter_impl(static_cast<T &&>(value), 123);
}

template <typename T, typename = void> struct awaitable_traits {
  using awaiter_t = decltype(get_awaiter(std::declval<T>()));
  using await_result_t = decltype(std::declval<awaiter_t>().await_resume());
};

template <typename TASK_CONTAINER> class when_all_ready_awaitable;
template <typename... TASKS>
class when_all_ready_awaitable<std::tuple<TASKS...>> {
public:
  explicit when_all_ready_awaitable(std::tuple<TASKS...> &&tasks) noexcept
    : m_tasks(std::move(tasks)) {}
  auto operator co_await() &&noexcept {
    struct awaiter {
      awaiter(when_all_ready_awaitable &awaitable) noexcept
        : m_awaitable(awaitable) {}
      bool await_ready() const noexcept { return false; }
      bool await_suspend() noexcept { return false; }
      std::tuple<TASKS...> &&await_resume() noexcept {
        return std::move(m_awaitable.m_tasks);
      }
      when_all_ready_awaitable& m_awaitable;
    };
    return awaiter{*this};
  }
  std::tuple<TASKS...> m_tasks;
};

inline void *operator new(std::size_t, void *__p) noexcept;

template <typename RESULT>
class when_all_task_promise final{
public:
  using coroutine_handle_t = std::coroutine_handle<when_all_task_promise>;
  RESULT &&result() &&;
};
template <typename RESULT> class when_all_task final {
public:
  using promise_type = when_all_task_promise<RESULT>;
  using coroutine_handle_t = typename promise_type::coroutine_handle_t;
  decltype(auto) result() &;
  decltype(auto) result() && {
    return std::move(m_coroutine.promise()).result();
  }
  decltype(auto) non_void_result() && {
    if constexpr (std::is_void_v<decltype(0)>)
      ;
    else
      return std::move(*this).result();
  }
  coroutine_handle_t m_coroutine;
};
class task;
template <typename AWAITABLE,
          typename RESULT = 
              typename awaitable_traits<AWAITABLE &&>::await_result_t,
          std::enable_if_t<!std::is_void_v<RESULT>, int> = 0>
when_all_task<RESULT> make_when_all_task(AWAITABLE awaitable);

template <typename... AWAITABLES>
inline auto when_all_ready(AWAITABLES &&... awaitables) {
  return when_all_ready_awaitable<
      std::tuple<when_all_task<typename awaitable_traits<
          std::remove_reference_t<AWAITABLES>>::await_result_t>...>>(
      std::make_tuple(
          make_when_all_task(std::forward<AWAITABLES>(awaitables))...));
}

template <typename FUNC, typename AWAITABLE> class fmap_awaiter {
  using awaiter_t = typename awaitable_traits<AWAITABLE &&>::awaiter_t;

public:
  fmap_awaiter(FUNC &&func, AWAITABLE &&awaitable) noexcept
      : m_func(static_cast<FUNC &&>(func)),
        m_awaiter(get_awaiter(static_cast<AWAITABLE &&>(awaitable))) {}
  decltype(auto) await_ready() noexcept {
    return static_cast<awaiter_t &&>(m_awaiter).await_ready();
  }
  template <typename PROMISE>
  decltype(auto) await_suspend(std::coroutine_handle<PROMISE> coro) noexcept {}
  template <typename AWAIT_RESULT =
                decltype(std::declval<awaiter_t>().await_resume()),
            std::enable_if_t<!std::is_void_v<AWAIT_RESULT>, int> = 0>
  decltype(auto) await_resume() noexcept {
    return std::invoke(static_cast<FUNC &&>(m_func),
                       static_cast<awaiter_t &&>(m_awaiter).await_resume());
  }

private:
  FUNC &&m_func;
  awaiter_t m_awaiter;
};
template <typename FUNC, typename AWAITABLE> class fmap_awaitable {
public:
  template <
      typename FUNC_ARG, typename AWAITABLE_ARG,
      std::enable_if_t<std::is_constructible_v<FUNC, FUNC_ARG &&> &&
                           std::is_constructible_v<AWAITABLE, AWAITABLE_ARG &&>,
                       int> = 0>
  explicit fmap_awaitable(FUNC_ARG &&func, AWAITABLE_ARG &&awaitable) noexcept
      : m_func(static_cast<FUNC_ARG &&>(func)),
        m_awaitable(static_cast<AWAITABLE_ARG &&>(awaitable)) {}
  auto operator co_await() && {
    return fmap_awaiter(static_cast<FUNC &&>(m_func),
                        static_cast<AWAITABLE &&>(m_awaitable));
  }

private:
  FUNC m_func;
  AWAITABLE m_awaitable;
};

template <typename FUNC, typename AWAITABLE>
auto fmap(FUNC &&func, AWAITABLE &&awaitable) {
  return fmap_awaitable<std::remove_cv_t<std::remove_reference_t<FUNC>>,
                        std::remove_cv_t<std::remove_reference_t<AWAITABLE>>>(
      std::forward<FUNC>(func), std::forward<AWAITABLE>(awaitable));
}
template <typename... AWAITABLES>
auto when_all(AWAITABLES &&... awaitables) {
  return fmap(
      [](auto &&taskTuple) {
        decltype(auto) __trans_tmp_1 = std::apply(
            [](auto &&... tasks) {
              return std::make_tuple(
                  static_cast<decltype(tasks)>(tasks).non_void_result()...);
            },
            static_cast<decltype(taskTuple)>(taskTuple));
        return __trans_tmp_1;
      },
      when_all_ready(std::forward<AWAITABLES>(awaitables)...));
}
class async_mutex_scoped_lock_operation;
class async_mutex {
public:
  async_mutex() noexcept;
  async_mutex_scoped_lock_operation scoped_lock_async() noexcept;
};
class async_mutex_lock {
public:
  explicit async_mutex_lock();
  ~async_mutex_lock();

private:
  async_mutex *m_mutex;
};
class async_mutex_scoped_lock_operation {
public:
  async_mutex_lock await_resume() const noexcept;
};
class task {
public:
  class promise_type {
  public:
    auto initial_suspend() noexcept { return std::suspend_always{}; }
    auto final_suspend() noexcept { return std::suspend_always{}; }
    task get_return_object() noexcept { return task{}; }
    void unhandled_exception() noexcept {}
    void return_value(int value) noexcept { v = value; }
    int result(){ return v; }
    int v = 0;
  };
public:
  task() noexcept {}
  auto operator co_await() const &noexcept {
    struct awaitable {
      std::coroutine_handle<promise_type> m_coroutine;
      decltype(auto) await_resume() {
        return this->m_coroutine.promise().result();
      }
    };
    return awaitable{};
  }
};
void foo() {
  (void) []() -> task {
    auto makeTask = [](int x) -> task { co_return x; };
    async_mutex_scoped_lock_operation op;
    co_await when_all(std::move(op), makeTask(123));
  }();
}