• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_DETAIL_JOIN_STATE_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_JOIN_STATE_H
17 
18 // This file is generated by tools/codegen/core/gen_join.py
19 
20 #include <grpc/support/port_platform.h>
21 
22 #include <tuple>
23 #include <type_traits>
24 #include <utility>
25 
26 #include "absl/log/check.h"
27 #include "absl/log/log.h"
28 #include "src/core/lib/debug/trace.h"
29 #include "src/core/lib/promise/detail/promise_like.h"
30 #include "src/core/lib/promise/poll.h"
31 #include "src/core/util/bitset.h"
32 #include "src/core/util/construct_destruct.h"
33 
34 namespace grpc_core {
35 namespace promise_detail {
36 template <class Traits, typename... Ps>
37 struct JoinState;
38 
39 template <class Traits, typename P0, typename P1>
40 struct JoinState<Traits, P0, P1> {
41   template <typename T>
42   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
43   using Promise0 = PromiseLike<P0>;
44   using Result0 = UnwrappedType<typename Promise0::Result>;
45   union {
46     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
47     GPR_NO_UNIQUE_ADDRESS Result0 result0;
48   };
49   using Promise1 = PromiseLike<P1>;
50   using Result1 = UnwrappedType<typename Promise1::Result>;
51   union {
52     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
53     GPR_NO_UNIQUE_ADDRESS Result1 result1;
54   };
55   GPR_NO_UNIQUE_ADDRESS BitSet<2> ready;
56   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1) {
57     Construct(&promise0, std::forward<P0>(p0));
58     Construct(&promise1, std::forward<P1>(p1));
59   }
60   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
61     DCHECK(other.ready.none());
62     Construct(&promise0, other.promise0);
63     Construct(&promise1, other.promise1);
64   }
65   JoinState& operator=(const JoinState& other) = delete;
66   JoinState& operator=(JoinState&& other) = delete;
67   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
68     DCHECK(other.ready.none());
69     Construct(&promise0, std::move(other.promise0));
70     Construct(&promise1, std::move(other.promise1));
71   }
72   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
73     if (ready.is_set(0)) {
74       Destruct(&result0);
75     } else {
76       Destruct(&promise0);
77     }
78     if (ready.is_set(1)) {
79       Destruct(&result1);
80     } else {
81       Destruct(&promise1);
82     }
83   }
84   using Result =
85       typename Traits::template ResultType<std::tuple<Result0, Result1>>;
86   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
87     if (!ready.is_set(0)) {
88       GRPC_TRACE_VLOG(promise_primitives, 2)
89           << "join[" << this << "]: begin poll joint 1/2";
90       auto poll = promise0();
91       GRPC_TRACE_VLOG(promise_primitives, 2)
92           << "join[" << this << "]: end poll joint 1/2 "
93           << (poll.pending()
94                   ? "pending"
95                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
96       if (auto* p = poll.value_if_ready()) {
97         if (Traits::IsOk(*p)) {
98           ready.set(0);
99           Destruct(&promise0);
100           Construct(&result0, Traits::Unwrapped(std::move(*p)));
101         } else {
102           return Traits::template EarlyReturn<Result>(std::move(*p));
103         }
104       }
105     } else {
106       GRPC_TRACE_VLOG(promise_primitives, 2)
107           << "join[" << this << "]: joint 1/2 already ready";
108     }
109     if (!ready.is_set(1)) {
110       GRPC_TRACE_VLOG(promise_primitives, 2)
111           << "join[" << this << "]: begin poll joint 2/2";
112       auto poll = promise1();
113       GRPC_TRACE_VLOG(promise_primitives, 2)
114           << "join[" << this << "]: end poll joint 2/2 "
115           << (poll.pending()
116                   ? "pending"
117                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
118       if (auto* p = poll.value_if_ready()) {
119         if (Traits::IsOk(*p)) {
120           ready.set(1);
121           Destruct(&promise1);
122           Construct(&result1, Traits::Unwrapped(std::move(*p)));
123         } else {
124           return Traits::template EarlyReturn<Result>(std::move(*p));
125         }
126       }
127     } else {
128       GRPC_TRACE_VLOG(promise_primitives, 2)
129           << "join[" << this << "]: joint 2/2 already ready";
130     }
131     if (ready.all()) {
132       return Traits::FinalReturn(std::move(result0), std::move(result1));
133     }
134     return Pending{};
135   }
136 };
137 
138 template <class Traits, typename P0, typename P1, typename P2>
139 struct JoinState<Traits, P0, P1, P2> {
140   template <typename T>
141   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
142   using Promise0 = PromiseLike<P0>;
143   using Result0 = UnwrappedType<typename Promise0::Result>;
144   union {
145     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
146     GPR_NO_UNIQUE_ADDRESS Result0 result0;
147   };
148   using Promise1 = PromiseLike<P1>;
149   using Result1 = UnwrappedType<typename Promise1::Result>;
150   union {
151     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
152     GPR_NO_UNIQUE_ADDRESS Result1 result1;
153   };
154   using Promise2 = PromiseLike<P2>;
155   using Result2 = UnwrappedType<typename Promise2::Result>;
156   union {
157     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
158     GPR_NO_UNIQUE_ADDRESS Result2 result2;
159   };
160   GPR_NO_UNIQUE_ADDRESS BitSet<3> ready;
161   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2) {
162     Construct(&promise0, std::forward<P0>(p0));
163     Construct(&promise1, std::forward<P1>(p1));
164     Construct(&promise2, std::forward<P2>(p2));
165   }
166   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
167     DCHECK(other.ready.none());
168     Construct(&promise0, other.promise0);
169     Construct(&promise1, other.promise1);
170     Construct(&promise2, other.promise2);
171   }
172   JoinState& operator=(const JoinState& other) = delete;
173   JoinState& operator=(JoinState&& other) = delete;
174   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
175     DCHECK(other.ready.none());
176     Construct(&promise0, std::move(other.promise0));
177     Construct(&promise1, std::move(other.promise1));
178     Construct(&promise2, std::move(other.promise2));
179   }
180   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
181     if (ready.is_set(0)) {
182       Destruct(&result0);
183     } else {
184       Destruct(&promise0);
185     }
186     if (ready.is_set(1)) {
187       Destruct(&result1);
188     } else {
189       Destruct(&promise1);
190     }
191     if (ready.is_set(2)) {
192       Destruct(&result2);
193     } else {
194       Destruct(&promise2);
195     }
196   }
197   using Result = typename Traits::template ResultType<
198       std::tuple<Result0, Result1, Result2>>;
199   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
200     if (!ready.is_set(0)) {
201       GRPC_TRACE_VLOG(promise_primitives, 2)
202           << "join[" << this << "]: begin poll joint 1/3";
203       auto poll = promise0();
204       GRPC_TRACE_VLOG(promise_primitives, 2)
205           << "join[" << this << "]: end poll joint 1/3 "
206           << (poll.pending()
207                   ? "pending"
208                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
209       if (auto* p = poll.value_if_ready()) {
210         if (Traits::IsOk(*p)) {
211           ready.set(0);
212           Destruct(&promise0);
213           Construct(&result0, Traits::Unwrapped(std::move(*p)));
214         } else {
215           return Traits::template EarlyReturn<Result>(std::move(*p));
216         }
217       }
218     } else {
219       GRPC_TRACE_VLOG(promise_primitives, 2)
220           << "join[" << this << "]: joint 1/3 already ready";
221     }
222     if (!ready.is_set(1)) {
223       GRPC_TRACE_VLOG(promise_primitives, 2)
224           << "join[" << this << "]: begin poll joint 2/3";
225       auto poll = promise1();
226       GRPC_TRACE_VLOG(promise_primitives, 2)
227           << "join[" << this << "]: end poll joint 2/3 "
228           << (poll.pending()
229                   ? "pending"
230                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
231       if (auto* p = poll.value_if_ready()) {
232         if (Traits::IsOk(*p)) {
233           ready.set(1);
234           Destruct(&promise1);
235           Construct(&result1, Traits::Unwrapped(std::move(*p)));
236         } else {
237           return Traits::template EarlyReturn<Result>(std::move(*p));
238         }
239       }
240     } else {
241       GRPC_TRACE_VLOG(promise_primitives, 2)
242           << "join[" << this << "]: joint 2/3 already ready";
243     }
244     if (!ready.is_set(2)) {
245       GRPC_TRACE_VLOG(promise_primitives, 2)
246           << "join[" << this << "]: begin poll joint 3/3";
247       auto poll = promise2();
248       GRPC_TRACE_VLOG(promise_primitives, 2)
249           << "join[" << this << "]: end poll joint 3/3 "
250           << (poll.pending()
251                   ? "pending"
252                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
253       if (auto* p = poll.value_if_ready()) {
254         if (Traits::IsOk(*p)) {
255           ready.set(2);
256           Destruct(&promise2);
257           Construct(&result2, Traits::Unwrapped(std::move(*p)));
258         } else {
259           return Traits::template EarlyReturn<Result>(std::move(*p));
260         }
261       }
262     } else {
263       GRPC_TRACE_VLOG(promise_primitives, 2)
264           << "join[" << this << "]: joint 3/3 already ready";
265     }
266     if (ready.all()) {
267       return Traits::FinalReturn(std::move(result0), std::move(result1),
268                                  std::move(result2));
269     }
270     return Pending{};
271   }
272 };
273 
274 template <class Traits, typename P0, typename P1, typename P2, typename P3>
275 struct JoinState<Traits, P0, P1, P2, P3> {
276   template <typename T>
277   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
278   using Promise0 = PromiseLike<P0>;
279   using Result0 = UnwrappedType<typename Promise0::Result>;
280   union {
281     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
282     GPR_NO_UNIQUE_ADDRESS Result0 result0;
283   };
284   using Promise1 = PromiseLike<P1>;
285   using Result1 = UnwrappedType<typename Promise1::Result>;
286   union {
287     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
288     GPR_NO_UNIQUE_ADDRESS Result1 result1;
289   };
290   using Promise2 = PromiseLike<P2>;
291   using Result2 = UnwrappedType<typename Promise2::Result>;
292   union {
293     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
294     GPR_NO_UNIQUE_ADDRESS Result2 result2;
295   };
296   using Promise3 = PromiseLike<P3>;
297   using Result3 = UnwrappedType<typename Promise3::Result>;
298   union {
299     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
300     GPR_NO_UNIQUE_ADDRESS Result3 result3;
301   };
302   GPR_NO_UNIQUE_ADDRESS BitSet<4> ready;
303   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
304                                                  P3&& p3) {
305     Construct(&promise0, std::forward<P0>(p0));
306     Construct(&promise1, std::forward<P1>(p1));
307     Construct(&promise2, std::forward<P2>(p2));
308     Construct(&promise3, std::forward<P3>(p3));
309   }
310   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
311     DCHECK(other.ready.none());
312     Construct(&promise0, other.promise0);
313     Construct(&promise1, other.promise1);
314     Construct(&promise2, other.promise2);
315     Construct(&promise3, other.promise3);
316   }
317   JoinState& operator=(const JoinState& other) = delete;
318   JoinState& operator=(JoinState&& other) = delete;
319   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
320     DCHECK(other.ready.none());
321     Construct(&promise0, std::move(other.promise0));
322     Construct(&promise1, std::move(other.promise1));
323     Construct(&promise2, std::move(other.promise2));
324     Construct(&promise3, std::move(other.promise3));
325   }
326   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
327     if (ready.is_set(0)) {
328       Destruct(&result0);
329     } else {
330       Destruct(&promise0);
331     }
332     if (ready.is_set(1)) {
333       Destruct(&result1);
334     } else {
335       Destruct(&promise1);
336     }
337     if (ready.is_set(2)) {
338       Destruct(&result2);
339     } else {
340       Destruct(&promise2);
341     }
342     if (ready.is_set(3)) {
343       Destruct(&result3);
344     } else {
345       Destruct(&promise3);
346     }
347   }
348   using Result = typename Traits::template ResultType<
349       std::tuple<Result0, Result1, Result2, Result3>>;
350   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
351     if (!ready.is_set(0)) {
352       GRPC_TRACE_VLOG(promise_primitives, 2)
353           << "join[" << this << "]: begin poll joint 1/4";
354       auto poll = promise0();
355       GRPC_TRACE_VLOG(promise_primitives, 2)
356           << "join[" << this << "]: end poll joint 1/4 "
357           << (poll.pending()
358                   ? "pending"
359                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
360       if (auto* p = poll.value_if_ready()) {
361         if (Traits::IsOk(*p)) {
362           ready.set(0);
363           Destruct(&promise0);
364           Construct(&result0, Traits::Unwrapped(std::move(*p)));
365         } else {
366           return Traits::template EarlyReturn<Result>(std::move(*p));
367         }
368       }
369     } else {
370       GRPC_TRACE_VLOG(promise_primitives, 2)
371           << "join[" << this << "]: joint 1/4 already ready";
372     }
373     if (!ready.is_set(1)) {
374       GRPC_TRACE_VLOG(promise_primitives, 2)
375           << "join[" << this << "]: begin poll joint 2/4";
376       auto poll = promise1();
377       GRPC_TRACE_VLOG(promise_primitives, 2)
378           << "join[" << this << "]: end poll joint 2/4 "
379           << (poll.pending()
380                   ? "pending"
381                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
382       if (auto* p = poll.value_if_ready()) {
383         if (Traits::IsOk(*p)) {
384           ready.set(1);
385           Destruct(&promise1);
386           Construct(&result1, Traits::Unwrapped(std::move(*p)));
387         } else {
388           return Traits::template EarlyReturn<Result>(std::move(*p));
389         }
390       }
391     } else {
392       GRPC_TRACE_VLOG(promise_primitives, 2)
393           << "join[" << this << "]: joint 2/4 already ready";
394     }
395     if (!ready.is_set(2)) {
396       GRPC_TRACE_VLOG(promise_primitives, 2)
397           << "join[" << this << "]: begin poll joint 3/4";
398       auto poll = promise2();
399       GRPC_TRACE_VLOG(promise_primitives, 2)
400           << "join[" << this << "]: end poll joint 3/4 "
401           << (poll.pending()
402                   ? "pending"
403                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
404       if (auto* p = poll.value_if_ready()) {
405         if (Traits::IsOk(*p)) {
406           ready.set(2);
407           Destruct(&promise2);
408           Construct(&result2, Traits::Unwrapped(std::move(*p)));
409         } else {
410           return Traits::template EarlyReturn<Result>(std::move(*p));
411         }
412       }
413     } else {
414       GRPC_TRACE_VLOG(promise_primitives, 2)
415           << "join[" << this << "]: joint 3/4 already ready";
416     }
417     if (!ready.is_set(3)) {
418       GRPC_TRACE_VLOG(promise_primitives, 2)
419           << "join[" << this << "]: begin poll joint 4/4";
420       auto poll = promise3();
421       GRPC_TRACE_VLOG(promise_primitives, 2)
422           << "join[" << this << "]: end poll joint 4/4 "
423           << (poll.pending()
424                   ? "pending"
425                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
426       if (auto* p = poll.value_if_ready()) {
427         if (Traits::IsOk(*p)) {
428           ready.set(3);
429           Destruct(&promise3);
430           Construct(&result3, Traits::Unwrapped(std::move(*p)));
431         } else {
432           return Traits::template EarlyReturn<Result>(std::move(*p));
433         }
434       }
435     } else {
436       GRPC_TRACE_VLOG(promise_primitives, 2)
437           << "join[" << this << "]: joint 4/4 already ready";
438     }
439     if (ready.all()) {
440       return Traits::FinalReturn(std::move(result0), std::move(result1),
441                                  std::move(result2), std::move(result3));
442     }
443     return Pending{};
444   }
445 };
446 
447 template <class Traits, typename P0, typename P1, typename P2, typename P3,
448           typename P4>
449 struct JoinState<Traits, P0, P1, P2, P3, P4> {
450   template <typename T>
451   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
452   using Promise0 = PromiseLike<P0>;
453   using Result0 = UnwrappedType<typename Promise0::Result>;
454   union {
455     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
456     GPR_NO_UNIQUE_ADDRESS Result0 result0;
457   };
458   using Promise1 = PromiseLike<P1>;
459   using Result1 = UnwrappedType<typename Promise1::Result>;
460   union {
461     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
462     GPR_NO_UNIQUE_ADDRESS Result1 result1;
463   };
464   using Promise2 = PromiseLike<P2>;
465   using Result2 = UnwrappedType<typename Promise2::Result>;
466   union {
467     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
468     GPR_NO_UNIQUE_ADDRESS Result2 result2;
469   };
470   using Promise3 = PromiseLike<P3>;
471   using Result3 = UnwrappedType<typename Promise3::Result>;
472   union {
473     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
474     GPR_NO_UNIQUE_ADDRESS Result3 result3;
475   };
476   using Promise4 = PromiseLike<P4>;
477   using Result4 = UnwrappedType<typename Promise4::Result>;
478   union {
479     GPR_NO_UNIQUE_ADDRESS Promise4 promise4;
480     GPR_NO_UNIQUE_ADDRESS Result4 result4;
481   };
482   GPR_NO_UNIQUE_ADDRESS BitSet<5> ready;
483   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
484                                                  P3&& p3, P4&& p4) {
485     Construct(&promise0, std::forward<P0>(p0));
486     Construct(&promise1, std::forward<P1>(p1));
487     Construct(&promise2, std::forward<P2>(p2));
488     Construct(&promise3, std::forward<P3>(p3));
489     Construct(&promise4, std::forward<P4>(p4));
490   }
491   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
492     DCHECK(other.ready.none());
493     Construct(&promise0, other.promise0);
494     Construct(&promise1, other.promise1);
495     Construct(&promise2, other.promise2);
496     Construct(&promise3, other.promise3);
497     Construct(&promise4, other.promise4);
498   }
499   JoinState& operator=(const JoinState& other) = delete;
500   JoinState& operator=(JoinState&& other) = delete;
501   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
502     DCHECK(other.ready.none());
503     Construct(&promise0, std::move(other.promise0));
504     Construct(&promise1, std::move(other.promise1));
505     Construct(&promise2, std::move(other.promise2));
506     Construct(&promise3, std::move(other.promise3));
507     Construct(&promise4, std::move(other.promise4));
508   }
509   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
510     if (ready.is_set(0)) {
511       Destruct(&result0);
512     } else {
513       Destruct(&promise0);
514     }
515     if (ready.is_set(1)) {
516       Destruct(&result1);
517     } else {
518       Destruct(&promise1);
519     }
520     if (ready.is_set(2)) {
521       Destruct(&result2);
522     } else {
523       Destruct(&promise2);
524     }
525     if (ready.is_set(3)) {
526       Destruct(&result3);
527     } else {
528       Destruct(&promise3);
529     }
530     if (ready.is_set(4)) {
531       Destruct(&result4);
532     } else {
533       Destruct(&promise4);
534     }
535   }
536   using Result = typename Traits::template ResultType<
537       std::tuple<Result0, Result1, Result2, Result3, Result4>>;
538   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
539     if (!ready.is_set(0)) {
540       GRPC_TRACE_VLOG(promise_primitives, 2)
541           << "join[" << this << "]: begin poll joint 1/5";
542       auto poll = promise0();
543       GRPC_TRACE_VLOG(promise_primitives, 2)
544           << "join[" << this << "]: end poll joint 1/5 "
545           << (poll.pending()
546                   ? "pending"
547                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
548       if (auto* p = poll.value_if_ready()) {
549         if (Traits::IsOk(*p)) {
550           ready.set(0);
551           Destruct(&promise0);
552           Construct(&result0, Traits::Unwrapped(std::move(*p)));
553         } else {
554           return Traits::template EarlyReturn<Result>(std::move(*p));
555         }
556       }
557     } else {
558       GRPC_TRACE_VLOG(promise_primitives, 2)
559           << "join[" << this << "]: joint 1/5 already ready";
560     }
561     if (!ready.is_set(1)) {
562       GRPC_TRACE_VLOG(promise_primitives, 2)
563           << "join[" << this << "]: begin poll joint 2/5";
564       auto poll = promise1();
565       GRPC_TRACE_VLOG(promise_primitives, 2)
566           << "join[" << this << "]: end poll joint 2/5 "
567           << (poll.pending()
568                   ? "pending"
569                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
570       if (auto* p = poll.value_if_ready()) {
571         if (Traits::IsOk(*p)) {
572           ready.set(1);
573           Destruct(&promise1);
574           Construct(&result1, Traits::Unwrapped(std::move(*p)));
575         } else {
576           return Traits::template EarlyReturn<Result>(std::move(*p));
577         }
578       }
579     } else {
580       GRPC_TRACE_VLOG(promise_primitives, 2)
581           << "join[" << this << "]: joint 2/5 already ready";
582     }
583     if (!ready.is_set(2)) {
584       GRPC_TRACE_VLOG(promise_primitives, 2)
585           << "join[" << this << "]: begin poll joint 3/5";
586       auto poll = promise2();
587       GRPC_TRACE_VLOG(promise_primitives, 2)
588           << "join[" << this << "]: end poll joint 3/5 "
589           << (poll.pending()
590                   ? "pending"
591                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
592       if (auto* p = poll.value_if_ready()) {
593         if (Traits::IsOk(*p)) {
594           ready.set(2);
595           Destruct(&promise2);
596           Construct(&result2, Traits::Unwrapped(std::move(*p)));
597         } else {
598           return Traits::template EarlyReturn<Result>(std::move(*p));
599         }
600       }
601     } else {
602       GRPC_TRACE_VLOG(promise_primitives, 2)
603           << "join[" << this << "]: joint 3/5 already ready";
604     }
605     if (!ready.is_set(3)) {
606       GRPC_TRACE_VLOG(promise_primitives, 2)
607           << "join[" << this << "]: begin poll joint 4/5";
608       auto poll = promise3();
609       GRPC_TRACE_VLOG(promise_primitives, 2)
610           << "join[" << this << "]: end poll joint 4/5 "
611           << (poll.pending()
612                   ? "pending"
613                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
614       if (auto* p = poll.value_if_ready()) {
615         if (Traits::IsOk(*p)) {
616           ready.set(3);
617           Destruct(&promise3);
618           Construct(&result3, Traits::Unwrapped(std::move(*p)));
619         } else {
620           return Traits::template EarlyReturn<Result>(std::move(*p));
621         }
622       }
623     } else {
624       GRPC_TRACE_VLOG(promise_primitives, 2)
625           << "join[" << this << "]: joint 4/5 already ready";
626     }
627     if (!ready.is_set(4)) {
628       GRPC_TRACE_VLOG(promise_primitives, 2)
629           << "join[" << this << "]: begin poll joint 5/5";
630       auto poll = promise4();
631       GRPC_TRACE_VLOG(promise_primitives, 2)
632           << "join[" << this << "]: end poll joint 5/5 "
633           << (poll.pending()
634                   ? "pending"
635                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
636       if (auto* p = poll.value_if_ready()) {
637         if (Traits::IsOk(*p)) {
638           ready.set(4);
639           Destruct(&promise4);
640           Construct(&result4, Traits::Unwrapped(std::move(*p)));
641         } else {
642           return Traits::template EarlyReturn<Result>(std::move(*p));
643         }
644       }
645     } else {
646       GRPC_TRACE_VLOG(promise_primitives, 2)
647           << "join[" << this << "]: joint 5/5 already ready";
648     }
649     if (ready.all()) {
650       return Traits::FinalReturn(std::move(result0), std::move(result1),
651                                  std::move(result2), std::move(result3),
652                                  std::move(result4));
653     }
654     return Pending{};
655   }
656 };
657 
658 template <class Traits, typename P0, typename P1, typename P2, typename P3,
659           typename P4, typename P5>
660 struct JoinState<Traits, P0, P1, P2, P3, P4, P5> {
661   template <typename T>
662   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
663   using Promise0 = PromiseLike<P0>;
664   using Result0 = UnwrappedType<typename Promise0::Result>;
665   union {
666     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
667     GPR_NO_UNIQUE_ADDRESS Result0 result0;
668   };
669   using Promise1 = PromiseLike<P1>;
670   using Result1 = UnwrappedType<typename Promise1::Result>;
671   union {
672     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
673     GPR_NO_UNIQUE_ADDRESS Result1 result1;
674   };
675   using Promise2 = PromiseLike<P2>;
676   using Result2 = UnwrappedType<typename Promise2::Result>;
677   union {
678     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
679     GPR_NO_UNIQUE_ADDRESS Result2 result2;
680   };
681   using Promise3 = PromiseLike<P3>;
682   using Result3 = UnwrappedType<typename Promise3::Result>;
683   union {
684     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
685     GPR_NO_UNIQUE_ADDRESS Result3 result3;
686   };
687   using Promise4 = PromiseLike<P4>;
688   using Result4 = UnwrappedType<typename Promise4::Result>;
689   union {
690     GPR_NO_UNIQUE_ADDRESS Promise4 promise4;
691     GPR_NO_UNIQUE_ADDRESS Result4 result4;
692   };
693   using Promise5 = PromiseLike<P5>;
694   using Result5 = UnwrappedType<typename Promise5::Result>;
695   union {
696     GPR_NO_UNIQUE_ADDRESS Promise5 promise5;
697     GPR_NO_UNIQUE_ADDRESS Result5 result5;
698   };
699   GPR_NO_UNIQUE_ADDRESS BitSet<6> ready;
700   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
701                                                  P3&& p3, P4&& p4, P5&& p5) {
702     Construct(&promise0, std::forward<P0>(p0));
703     Construct(&promise1, std::forward<P1>(p1));
704     Construct(&promise2, std::forward<P2>(p2));
705     Construct(&promise3, std::forward<P3>(p3));
706     Construct(&promise4, std::forward<P4>(p4));
707     Construct(&promise5, std::forward<P5>(p5));
708   }
709   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
710     DCHECK(other.ready.none());
711     Construct(&promise0, other.promise0);
712     Construct(&promise1, other.promise1);
713     Construct(&promise2, other.promise2);
714     Construct(&promise3, other.promise3);
715     Construct(&promise4, other.promise4);
716     Construct(&promise5, other.promise5);
717   }
718   JoinState& operator=(const JoinState& other) = delete;
719   JoinState& operator=(JoinState&& other) = delete;
720   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
721     DCHECK(other.ready.none());
722     Construct(&promise0, std::move(other.promise0));
723     Construct(&promise1, std::move(other.promise1));
724     Construct(&promise2, std::move(other.promise2));
725     Construct(&promise3, std::move(other.promise3));
726     Construct(&promise4, std::move(other.promise4));
727     Construct(&promise5, std::move(other.promise5));
728   }
729   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
730     if (ready.is_set(0)) {
731       Destruct(&result0);
732     } else {
733       Destruct(&promise0);
734     }
735     if (ready.is_set(1)) {
736       Destruct(&result1);
737     } else {
738       Destruct(&promise1);
739     }
740     if (ready.is_set(2)) {
741       Destruct(&result2);
742     } else {
743       Destruct(&promise2);
744     }
745     if (ready.is_set(3)) {
746       Destruct(&result3);
747     } else {
748       Destruct(&promise3);
749     }
750     if (ready.is_set(4)) {
751       Destruct(&result4);
752     } else {
753       Destruct(&promise4);
754     }
755     if (ready.is_set(5)) {
756       Destruct(&result5);
757     } else {
758       Destruct(&promise5);
759     }
760   }
761   using Result = typename Traits::template ResultType<
762       std::tuple<Result0, Result1, Result2, Result3, Result4, Result5>>;
763   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
764     if (!ready.is_set(0)) {
765       GRPC_TRACE_VLOG(promise_primitives, 2)
766           << "join[" << this << "]: begin poll joint 1/6";
767       auto poll = promise0();
768       GRPC_TRACE_VLOG(promise_primitives, 2)
769           << "join[" << this << "]: end poll joint 1/6 "
770           << (poll.pending()
771                   ? "pending"
772                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
773       if (auto* p = poll.value_if_ready()) {
774         if (Traits::IsOk(*p)) {
775           ready.set(0);
776           Destruct(&promise0);
777           Construct(&result0, Traits::Unwrapped(std::move(*p)));
778         } else {
779           return Traits::template EarlyReturn<Result>(std::move(*p));
780         }
781       }
782     } else {
783       GRPC_TRACE_VLOG(promise_primitives, 2)
784           << "join[" << this << "]: joint 1/6 already ready";
785     }
786     if (!ready.is_set(1)) {
787       GRPC_TRACE_VLOG(promise_primitives, 2)
788           << "join[" << this << "]: begin poll joint 2/6";
789       auto poll = promise1();
790       GRPC_TRACE_VLOG(promise_primitives, 2)
791           << "join[" << this << "]: end poll joint 2/6 "
792           << (poll.pending()
793                   ? "pending"
794                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
795       if (auto* p = poll.value_if_ready()) {
796         if (Traits::IsOk(*p)) {
797           ready.set(1);
798           Destruct(&promise1);
799           Construct(&result1, Traits::Unwrapped(std::move(*p)));
800         } else {
801           return Traits::template EarlyReturn<Result>(std::move(*p));
802         }
803       }
804     } else {
805       GRPC_TRACE_VLOG(promise_primitives, 2)
806           << "join[" << this << "]: joint 2/6 already ready";
807     }
808     if (!ready.is_set(2)) {
809       GRPC_TRACE_VLOG(promise_primitives, 2)
810           << "join[" << this << "]: begin poll joint 3/6";
811       auto poll = promise2();
812       GRPC_TRACE_VLOG(promise_primitives, 2)
813           << "join[" << this << "]: end poll joint 3/6 "
814           << (poll.pending()
815                   ? "pending"
816                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
817       if (auto* p = poll.value_if_ready()) {
818         if (Traits::IsOk(*p)) {
819           ready.set(2);
820           Destruct(&promise2);
821           Construct(&result2, Traits::Unwrapped(std::move(*p)));
822         } else {
823           return Traits::template EarlyReturn<Result>(std::move(*p));
824         }
825       }
826     } else {
827       GRPC_TRACE_VLOG(promise_primitives, 2)
828           << "join[" << this << "]: joint 3/6 already ready";
829     }
830     if (!ready.is_set(3)) {
831       GRPC_TRACE_VLOG(promise_primitives, 2)
832           << "join[" << this << "]: begin poll joint 4/6";
833       auto poll = promise3();
834       GRPC_TRACE_VLOG(promise_primitives, 2)
835           << "join[" << this << "]: end poll joint 4/6 "
836           << (poll.pending()
837                   ? "pending"
838                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
839       if (auto* p = poll.value_if_ready()) {
840         if (Traits::IsOk(*p)) {
841           ready.set(3);
842           Destruct(&promise3);
843           Construct(&result3, Traits::Unwrapped(std::move(*p)));
844         } else {
845           return Traits::template EarlyReturn<Result>(std::move(*p));
846         }
847       }
848     } else {
849       GRPC_TRACE_VLOG(promise_primitives, 2)
850           << "join[" << this << "]: joint 4/6 already ready";
851     }
852     if (!ready.is_set(4)) {
853       GRPC_TRACE_VLOG(promise_primitives, 2)
854           << "join[" << this << "]: begin poll joint 5/6";
855       auto poll = promise4();
856       GRPC_TRACE_VLOG(promise_primitives, 2)
857           << "join[" << this << "]: end poll joint 5/6 "
858           << (poll.pending()
859                   ? "pending"
860                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
861       if (auto* p = poll.value_if_ready()) {
862         if (Traits::IsOk(*p)) {
863           ready.set(4);
864           Destruct(&promise4);
865           Construct(&result4, Traits::Unwrapped(std::move(*p)));
866         } else {
867           return Traits::template EarlyReturn<Result>(std::move(*p));
868         }
869       }
870     } else {
871       GRPC_TRACE_VLOG(promise_primitives, 2)
872           << "join[" << this << "]: joint 5/6 already ready";
873     }
874     if (!ready.is_set(5)) {
875       GRPC_TRACE_VLOG(promise_primitives, 2)
876           << "join[" << this << "]: begin poll joint 6/6";
877       auto poll = promise5();
878       GRPC_TRACE_VLOG(promise_primitives, 2)
879           << "join[" << this << "]: end poll joint 6/6 "
880           << (poll.pending()
881                   ? "pending"
882                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
883       if (auto* p = poll.value_if_ready()) {
884         if (Traits::IsOk(*p)) {
885           ready.set(5);
886           Destruct(&promise5);
887           Construct(&result5, Traits::Unwrapped(std::move(*p)));
888         } else {
889           return Traits::template EarlyReturn<Result>(std::move(*p));
890         }
891       }
892     } else {
893       GRPC_TRACE_VLOG(promise_primitives, 2)
894           << "join[" << this << "]: joint 6/6 already ready";
895     }
896     if (ready.all()) {
897       return Traits::FinalReturn(std::move(result0), std::move(result1),
898                                  std::move(result2), std::move(result3),
899                                  std::move(result4), std::move(result5));
900     }
901     return Pending{};
902   }
903 };
904 
905 template <class Traits, typename P0, typename P1, typename P2, typename P3,
906           typename P4, typename P5, typename P6>
907 struct JoinState<Traits, P0, P1, P2, P3, P4, P5, P6> {
908   template <typename T>
909   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
910   using Promise0 = PromiseLike<P0>;
911   using Result0 = UnwrappedType<typename Promise0::Result>;
912   union {
913     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
914     GPR_NO_UNIQUE_ADDRESS Result0 result0;
915   };
916   using Promise1 = PromiseLike<P1>;
917   using Result1 = UnwrappedType<typename Promise1::Result>;
918   union {
919     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
920     GPR_NO_UNIQUE_ADDRESS Result1 result1;
921   };
922   using Promise2 = PromiseLike<P2>;
923   using Result2 = UnwrappedType<typename Promise2::Result>;
924   union {
925     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
926     GPR_NO_UNIQUE_ADDRESS Result2 result2;
927   };
928   using Promise3 = PromiseLike<P3>;
929   using Result3 = UnwrappedType<typename Promise3::Result>;
930   union {
931     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
932     GPR_NO_UNIQUE_ADDRESS Result3 result3;
933   };
934   using Promise4 = PromiseLike<P4>;
935   using Result4 = UnwrappedType<typename Promise4::Result>;
936   union {
937     GPR_NO_UNIQUE_ADDRESS Promise4 promise4;
938     GPR_NO_UNIQUE_ADDRESS Result4 result4;
939   };
940   using Promise5 = PromiseLike<P5>;
941   using Result5 = UnwrappedType<typename Promise5::Result>;
942   union {
943     GPR_NO_UNIQUE_ADDRESS Promise5 promise5;
944     GPR_NO_UNIQUE_ADDRESS Result5 result5;
945   };
946   using Promise6 = PromiseLike<P6>;
947   using Result6 = UnwrappedType<typename Promise6::Result>;
948   union {
949     GPR_NO_UNIQUE_ADDRESS Promise6 promise6;
950     GPR_NO_UNIQUE_ADDRESS Result6 result6;
951   };
952   GPR_NO_UNIQUE_ADDRESS BitSet<7> ready;
953   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
954                                                  P3&& p3, P4&& p4, P5&& p5,
955                                                  P6&& p6) {
956     Construct(&promise0, std::forward<P0>(p0));
957     Construct(&promise1, std::forward<P1>(p1));
958     Construct(&promise2, std::forward<P2>(p2));
959     Construct(&promise3, std::forward<P3>(p3));
960     Construct(&promise4, std::forward<P4>(p4));
961     Construct(&promise5, std::forward<P5>(p5));
962     Construct(&promise6, std::forward<P6>(p6));
963   }
964   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
965     DCHECK(other.ready.none());
966     Construct(&promise0, other.promise0);
967     Construct(&promise1, other.promise1);
968     Construct(&promise2, other.promise2);
969     Construct(&promise3, other.promise3);
970     Construct(&promise4, other.promise4);
971     Construct(&promise5, other.promise5);
972     Construct(&promise6, other.promise6);
973   }
974   JoinState& operator=(const JoinState& other) = delete;
975   JoinState& operator=(JoinState&& other) = delete;
976   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
977     DCHECK(other.ready.none());
978     Construct(&promise0, std::move(other.promise0));
979     Construct(&promise1, std::move(other.promise1));
980     Construct(&promise2, std::move(other.promise2));
981     Construct(&promise3, std::move(other.promise3));
982     Construct(&promise4, std::move(other.promise4));
983     Construct(&promise5, std::move(other.promise5));
984     Construct(&promise6, std::move(other.promise6));
985   }
986   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
987     if (ready.is_set(0)) {
988       Destruct(&result0);
989     } else {
990       Destruct(&promise0);
991     }
992     if (ready.is_set(1)) {
993       Destruct(&result1);
994     } else {
995       Destruct(&promise1);
996     }
997     if (ready.is_set(2)) {
998       Destruct(&result2);
999     } else {
1000       Destruct(&promise2);
1001     }
1002     if (ready.is_set(3)) {
1003       Destruct(&result3);
1004     } else {
1005       Destruct(&promise3);
1006     }
1007     if (ready.is_set(4)) {
1008       Destruct(&result4);
1009     } else {
1010       Destruct(&promise4);
1011     }
1012     if (ready.is_set(5)) {
1013       Destruct(&result5);
1014     } else {
1015       Destruct(&promise5);
1016     }
1017     if (ready.is_set(6)) {
1018       Destruct(&result6);
1019     } else {
1020       Destruct(&promise6);
1021     }
1022   }
1023   using Result = typename Traits::template ResultType<std::tuple<
1024       Result0, Result1, Result2, Result3, Result4, Result5, Result6>>;
1025   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
1026     if (!ready.is_set(0)) {
1027       GRPC_TRACE_VLOG(promise_primitives, 2)
1028           << "join[" << this << "]: begin poll joint 1/7";
1029       auto poll = promise0();
1030       GRPC_TRACE_VLOG(promise_primitives, 2)
1031           << "join[" << this << "]: end poll joint 1/7 "
1032           << (poll.pending()
1033                   ? "pending"
1034                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1035       if (auto* p = poll.value_if_ready()) {
1036         if (Traits::IsOk(*p)) {
1037           ready.set(0);
1038           Destruct(&promise0);
1039           Construct(&result0, Traits::Unwrapped(std::move(*p)));
1040         } else {
1041           return Traits::template EarlyReturn<Result>(std::move(*p));
1042         }
1043       }
1044     } else {
1045       GRPC_TRACE_VLOG(promise_primitives, 2)
1046           << "join[" << this << "]: joint 1/7 already ready";
1047     }
1048     if (!ready.is_set(1)) {
1049       GRPC_TRACE_VLOG(promise_primitives, 2)
1050           << "join[" << this << "]: begin poll joint 2/7";
1051       auto poll = promise1();
1052       GRPC_TRACE_VLOG(promise_primitives, 2)
1053           << "join[" << this << "]: end poll joint 2/7 "
1054           << (poll.pending()
1055                   ? "pending"
1056                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1057       if (auto* p = poll.value_if_ready()) {
1058         if (Traits::IsOk(*p)) {
1059           ready.set(1);
1060           Destruct(&promise1);
1061           Construct(&result1, Traits::Unwrapped(std::move(*p)));
1062         } else {
1063           return Traits::template EarlyReturn<Result>(std::move(*p));
1064         }
1065       }
1066     } else {
1067       GRPC_TRACE_VLOG(promise_primitives, 2)
1068           << "join[" << this << "]: joint 2/7 already ready";
1069     }
1070     if (!ready.is_set(2)) {
1071       GRPC_TRACE_VLOG(promise_primitives, 2)
1072           << "join[" << this << "]: begin poll joint 3/7";
1073       auto poll = promise2();
1074       GRPC_TRACE_VLOG(promise_primitives, 2)
1075           << "join[" << this << "]: end poll joint 3/7 "
1076           << (poll.pending()
1077                   ? "pending"
1078                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1079       if (auto* p = poll.value_if_ready()) {
1080         if (Traits::IsOk(*p)) {
1081           ready.set(2);
1082           Destruct(&promise2);
1083           Construct(&result2, Traits::Unwrapped(std::move(*p)));
1084         } else {
1085           return Traits::template EarlyReturn<Result>(std::move(*p));
1086         }
1087       }
1088     } else {
1089       GRPC_TRACE_VLOG(promise_primitives, 2)
1090           << "join[" << this << "]: joint 3/7 already ready";
1091     }
1092     if (!ready.is_set(3)) {
1093       GRPC_TRACE_VLOG(promise_primitives, 2)
1094           << "join[" << this << "]: begin poll joint 4/7";
1095       auto poll = promise3();
1096       GRPC_TRACE_VLOG(promise_primitives, 2)
1097           << "join[" << this << "]: end poll joint 4/7 "
1098           << (poll.pending()
1099                   ? "pending"
1100                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1101       if (auto* p = poll.value_if_ready()) {
1102         if (Traits::IsOk(*p)) {
1103           ready.set(3);
1104           Destruct(&promise3);
1105           Construct(&result3, Traits::Unwrapped(std::move(*p)));
1106         } else {
1107           return Traits::template EarlyReturn<Result>(std::move(*p));
1108         }
1109       }
1110     } else {
1111       GRPC_TRACE_VLOG(promise_primitives, 2)
1112           << "join[" << this << "]: joint 4/7 already ready";
1113     }
1114     if (!ready.is_set(4)) {
1115       GRPC_TRACE_VLOG(promise_primitives, 2)
1116           << "join[" << this << "]: begin poll joint 5/7";
1117       auto poll = promise4();
1118       GRPC_TRACE_VLOG(promise_primitives, 2)
1119           << "join[" << this << "]: end poll joint 5/7 "
1120           << (poll.pending()
1121                   ? "pending"
1122                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1123       if (auto* p = poll.value_if_ready()) {
1124         if (Traits::IsOk(*p)) {
1125           ready.set(4);
1126           Destruct(&promise4);
1127           Construct(&result4, Traits::Unwrapped(std::move(*p)));
1128         } else {
1129           return Traits::template EarlyReturn<Result>(std::move(*p));
1130         }
1131       }
1132     } else {
1133       GRPC_TRACE_VLOG(promise_primitives, 2)
1134           << "join[" << this << "]: joint 5/7 already ready";
1135     }
1136     if (!ready.is_set(5)) {
1137       GRPC_TRACE_VLOG(promise_primitives, 2)
1138           << "join[" << this << "]: begin poll joint 6/7";
1139       auto poll = promise5();
1140       GRPC_TRACE_VLOG(promise_primitives, 2)
1141           << "join[" << this << "]: end poll joint 6/7 "
1142           << (poll.pending()
1143                   ? "pending"
1144                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1145       if (auto* p = poll.value_if_ready()) {
1146         if (Traits::IsOk(*p)) {
1147           ready.set(5);
1148           Destruct(&promise5);
1149           Construct(&result5, Traits::Unwrapped(std::move(*p)));
1150         } else {
1151           return Traits::template EarlyReturn<Result>(std::move(*p));
1152         }
1153       }
1154     } else {
1155       GRPC_TRACE_VLOG(promise_primitives, 2)
1156           << "join[" << this << "]: joint 6/7 already ready";
1157     }
1158     if (!ready.is_set(6)) {
1159       GRPC_TRACE_VLOG(promise_primitives, 2)
1160           << "join[" << this << "]: begin poll joint 7/7";
1161       auto poll = promise6();
1162       GRPC_TRACE_VLOG(promise_primitives, 2)
1163           << "join[" << this << "]: end poll joint 7/7 "
1164           << (poll.pending()
1165                   ? "pending"
1166                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1167       if (auto* p = poll.value_if_ready()) {
1168         if (Traits::IsOk(*p)) {
1169           ready.set(6);
1170           Destruct(&promise6);
1171           Construct(&result6, Traits::Unwrapped(std::move(*p)));
1172         } else {
1173           return Traits::template EarlyReturn<Result>(std::move(*p));
1174         }
1175       }
1176     } else {
1177       GRPC_TRACE_VLOG(promise_primitives, 2)
1178           << "join[" << this << "]: joint 7/7 already ready";
1179     }
1180     if (ready.all()) {
1181       return Traits::FinalReturn(std::move(result0), std::move(result1),
1182                                  std::move(result2), std::move(result3),
1183                                  std::move(result4), std::move(result5),
1184                                  std::move(result6));
1185     }
1186     return Pending{};
1187   }
1188 };
1189 
1190 template <class Traits, typename P0, typename P1, typename P2, typename P3,
1191           typename P4, typename P5, typename P6, typename P7>
1192 struct JoinState<Traits, P0, P1, P2, P3, P4, P5, P6, P7> {
1193   template <typename T>
1194   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
1195   using Promise0 = PromiseLike<P0>;
1196   using Result0 = UnwrappedType<typename Promise0::Result>;
1197   union {
1198     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
1199     GPR_NO_UNIQUE_ADDRESS Result0 result0;
1200   };
1201   using Promise1 = PromiseLike<P1>;
1202   using Result1 = UnwrappedType<typename Promise1::Result>;
1203   union {
1204     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
1205     GPR_NO_UNIQUE_ADDRESS Result1 result1;
1206   };
1207   using Promise2 = PromiseLike<P2>;
1208   using Result2 = UnwrappedType<typename Promise2::Result>;
1209   union {
1210     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
1211     GPR_NO_UNIQUE_ADDRESS Result2 result2;
1212   };
1213   using Promise3 = PromiseLike<P3>;
1214   using Result3 = UnwrappedType<typename Promise3::Result>;
1215   union {
1216     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
1217     GPR_NO_UNIQUE_ADDRESS Result3 result3;
1218   };
1219   using Promise4 = PromiseLike<P4>;
1220   using Result4 = UnwrappedType<typename Promise4::Result>;
1221   union {
1222     GPR_NO_UNIQUE_ADDRESS Promise4 promise4;
1223     GPR_NO_UNIQUE_ADDRESS Result4 result4;
1224   };
1225   using Promise5 = PromiseLike<P5>;
1226   using Result5 = UnwrappedType<typename Promise5::Result>;
1227   union {
1228     GPR_NO_UNIQUE_ADDRESS Promise5 promise5;
1229     GPR_NO_UNIQUE_ADDRESS Result5 result5;
1230   };
1231   using Promise6 = PromiseLike<P6>;
1232   using Result6 = UnwrappedType<typename Promise6::Result>;
1233   union {
1234     GPR_NO_UNIQUE_ADDRESS Promise6 promise6;
1235     GPR_NO_UNIQUE_ADDRESS Result6 result6;
1236   };
1237   using Promise7 = PromiseLike<P7>;
1238   using Result7 = UnwrappedType<typename Promise7::Result>;
1239   union {
1240     GPR_NO_UNIQUE_ADDRESS Promise7 promise7;
1241     GPR_NO_UNIQUE_ADDRESS Result7 result7;
1242   };
1243   GPR_NO_UNIQUE_ADDRESS BitSet<8> ready;
1244   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
1245                                                  P3&& p3, P4&& p4, P5&& p5,
1246                                                  P6&& p6, P7&& p7) {
1247     Construct(&promise0, std::forward<P0>(p0));
1248     Construct(&promise1, std::forward<P1>(p1));
1249     Construct(&promise2, std::forward<P2>(p2));
1250     Construct(&promise3, std::forward<P3>(p3));
1251     Construct(&promise4, std::forward<P4>(p4));
1252     Construct(&promise5, std::forward<P5>(p5));
1253     Construct(&promise6, std::forward<P6>(p6));
1254     Construct(&promise7, std::forward<P7>(p7));
1255   }
1256   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
1257     DCHECK(other.ready.none());
1258     Construct(&promise0, other.promise0);
1259     Construct(&promise1, other.promise1);
1260     Construct(&promise2, other.promise2);
1261     Construct(&promise3, other.promise3);
1262     Construct(&promise4, other.promise4);
1263     Construct(&promise5, other.promise5);
1264     Construct(&promise6, other.promise6);
1265     Construct(&promise7, other.promise7);
1266   }
1267   JoinState& operator=(const JoinState& other) = delete;
1268   JoinState& operator=(JoinState&& other) = delete;
1269   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
1270     DCHECK(other.ready.none());
1271     Construct(&promise0, std::move(other.promise0));
1272     Construct(&promise1, std::move(other.promise1));
1273     Construct(&promise2, std::move(other.promise2));
1274     Construct(&promise3, std::move(other.promise3));
1275     Construct(&promise4, std::move(other.promise4));
1276     Construct(&promise5, std::move(other.promise5));
1277     Construct(&promise6, std::move(other.promise6));
1278     Construct(&promise7, std::move(other.promise7));
1279   }
1280   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
1281     if (ready.is_set(0)) {
1282       Destruct(&result0);
1283     } else {
1284       Destruct(&promise0);
1285     }
1286     if (ready.is_set(1)) {
1287       Destruct(&result1);
1288     } else {
1289       Destruct(&promise1);
1290     }
1291     if (ready.is_set(2)) {
1292       Destruct(&result2);
1293     } else {
1294       Destruct(&promise2);
1295     }
1296     if (ready.is_set(3)) {
1297       Destruct(&result3);
1298     } else {
1299       Destruct(&promise3);
1300     }
1301     if (ready.is_set(4)) {
1302       Destruct(&result4);
1303     } else {
1304       Destruct(&promise4);
1305     }
1306     if (ready.is_set(5)) {
1307       Destruct(&result5);
1308     } else {
1309       Destruct(&promise5);
1310     }
1311     if (ready.is_set(6)) {
1312       Destruct(&result6);
1313     } else {
1314       Destruct(&promise6);
1315     }
1316     if (ready.is_set(7)) {
1317       Destruct(&result7);
1318     } else {
1319       Destruct(&promise7);
1320     }
1321   }
1322   using Result = typename Traits::template ResultType<std::tuple<
1323       Result0, Result1, Result2, Result3, Result4, Result5, Result6, Result7>>;
1324   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
1325     if (!ready.is_set(0)) {
1326       GRPC_TRACE_VLOG(promise_primitives, 2)
1327           << "join[" << this << "]: begin poll joint 1/8";
1328       auto poll = promise0();
1329       GRPC_TRACE_VLOG(promise_primitives, 2)
1330           << "join[" << this << "]: end poll joint 1/8 "
1331           << (poll.pending()
1332                   ? "pending"
1333                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1334       if (auto* p = poll.value_if_ready()) {
1335         if (Traits::IsOk(*p)) {
1336           ready.set(0);
1337           Destruct(&promise0);
1338           Construct(&result0, Traits::Unwrapped(std::move(*p)));
1339         } else {
1340           return Traits::template EarlyReturn<Result>(std::move(*p));
1341         }
1342       }
1343     } else {
1344       GRPC_TRACE_VLOG(promise_primitives, 2)
1345           << "join[" << this << "]: joint 1/8 already ready";
1346     }
1347     if (!ready.is_set(1)) {
1348       GRPC_TRACE_VLOG(promise_primitives, 2)
1349           << "join[" << this << "]: begin poll joint 2/8";
1350       auto poll = promise1();
1351       GRPC_TRACE_VLOG(promise_primitives, 2)
1352           << "join[" << this << "]: end poll joint 2/8 "
1353           << (poll.pending()
1354                   ? "pending"
1355                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1356       if (auto* p = poll.value_if_ready()) {
1357         if (Traits::IsOk(*p)) {
1358           ready.set(1);
1359           Destruct(&promise1);
1360           Construct(&result1, Traits::Unwrapped(std::move(*p)));
1361         } else {
1362           return Traits::template EarlyReturn<Result>(std::move(*p));
1363         }
1364       }
1365     } else {
1366       GRPC_TRACE_VLOG(promise_primitives, 2)
1367           << "join[" << this << "]: joint 2/8 already ready";
1368     }
1369     if (!ready.is_set(2)) {
1370       GRPC_TRACE_VLOG(promise_primitives, 2)
1371           << "join[" << this << "]: begin poll joint 3/8";
1372       auto poll = promise2();
1373       GRPC_TRACE_VLOG(promise_primitives, 2)
1374           << "join[" << this << "]: end poll joint 3/8 "
1375           << (poll.pending()
1376                   ? "pending"
1377                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1378       if (auto* p = poll.value_if_ready()) {
1379         if (Traits::IsOk(*p)) {
1380           ready.set(2);
1381           Destruct(&promise2);
1382           Construct(&result2, Traits::Unwrapped(std::move(*p)));
1383         } else {
1384           return Traits::template EarlyReturn<Result>(std::move(*p));
1385         }
1386       }
1387     } else {
1388       GRPC_TRACE_VLOG(promise_primitives, 2)
1389           << "join[" << this << "]: joint 3/8 already ready";
1390     }
1391     if (!ready.is_set(3)) {
1392       GRPC_TRACE_VLOG(promise_primitives, 2)
1393           << "join[" << this << "]: begin poll joint 4/8";
1394       auto poll = promise3();
1395       GRPC_TRACE_VLOG(promise_primitives, 2)
1396           << "join[" << this << "]: end poll joint 4/8 "
1397           << (poll.pending()
1398                   ? "pending"
1399                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1400       if (auto* p = poll.value_if_ready()) {
1401         if (Traits::IsOk(*p)) {
1402           ready.set(3);
1403           Destruct(&promise3);
1404           Construct(&result3, Traits::Unwrapped(std::move(*p)));
1405         } else {
1406           return Traits::template EarlyReturn<Result>(std::move(*p));
1407         }
1408       }
1409     } else {
1410       GRPC_TRACE_VLOG(promise_primitives, 2)
1411           << "join[" << this << "]: joint 4/8 already ready";
1412     }
1413     if (!ready.is_set(4)) {
1414       GRPC_TRACE_VLOG(promise_primitives, 2)
1415           << "join[" << this << "]: begin poll joint 5/8";
1416       auto poll = promise4();
1417       GRPC_TRACE_VLOG(promise_primitives, 2)
1418           << "join[" << this << "]: end poll joint 5/8 "
1419           << (poll.pending()
1420                   ? "pending"
1421                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1422       if (auto* p = poll.value_if_ready()) {
1423         if (Traits::IsOk(*p)) {
1424           ready.set(4);
1425           Destruct(&promise4);
1426           Construct(&result4, Traits::Unwrapped(std::move(*p)));
1427         } else {
1428           return Traits::template EarlyReturn<Result>(std::move(*p));
1429         }
1430       }
1431     } else {
1432       GRPC_TRACE_VLOG(promise_primitives, 2)
1433           << "join[" << this << "]: joint 5/8 already ready";
1434     }
1435     if (!ready.is_set(5)) {
1436       GRPC_TRACE_VLOG(promise_primitives, 2)
1437           << "join[" << this << "]: begin poll joint 6/8";
1438       auto poll = promise5();
1439       GRPC_TRACE_VLOG(promise_primitives, 2)
1440           << "join[" << this << "]: end poll joint 6/8 "
1441           << (poll.pending()
1442                   ? "pending"
1443                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1444       if (auto* p = poll.value_if_ready()) {
1445         if (Traits::IsOk(*p)) {
1446           ready.set(5);
1447           Destruct(&promise5);
1448           Construct(&result5, Traits::Unwrapped(std::move(*p)));
1449         } else {
1450           return Traits::template EarlyReturn<Result>(std::move(*p));
1451         }
1452       }
1453     } else {
1454       GRPC_TRACE_VLOG(promise_primitives, 2)
1455           << "join[" << this << "]: joint 6/8 already ready";
1456     }
1457     if (!ready.is_set(6)) {
1458       GRPC_TRACE_VLOG(promise_primitives, 2)
1459           << "join[" << this << "]: begin poll joint 7/8";
1460       auto poll = promise6();
1461       GRPC_TRACE_VLOG(promise_primitives, 2)
1462           << "join[" << this << "]: end poll joint 7/8 "
1463           << (poll.pending()
1464                   ? "pending"
1465                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1466       if (auto* p = poll.value_if_ready()) {
1467         if (Traits::IsOk(*p)) {
1468           ready.set(6);
1469           Destruct(&promise6);
1470           Construct(&result6, Traits::Unwrapped(std::move(*p)));
1471         } else {
1472           return Traits::template EarlyReturn<Result>(std::move(*p));
1473         }
1474       }
1475     } else {
1476       GRPC_TRACE_VLOG(promise_primitives, 2)
1477           << "join[" << this << "]: joint 7/8 already ready";
1478     }
1479     if (!ready.is_set(7)) {
1480       GRPC_TRACE_VLOG(promise_primitives, 2)
1481           << "join[" << this << "]: begin poll joint 8/8";
1482       auto poll = promise7();
1483       GRPC_TRACE_VLOG(promise_primitives, 2)
1484           << "join[" << this << "]: end poll joint 8/8 "
1485           << (poll.pending()
1486                   ? "pending"
1487                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1488       if (auto* p = poll.value_if_ready()) {
1489         if (Traits::IsOk(*p)) {
1490           ready.set(7);
1491           Destruct(&promise7);
1492           Construct(&result7, Traits::Unwrapped(std::move(*p)));
1493         } else {
1494           return Traits::template EarlyReturn<Result>(std::move(*p));
1495         }
1496       }
1497     } else {
1498       GRPC_TRACE_VLOG(promise_primitives, 2)
1499           << "join[" << this << "]: joint 8/8 already ready";
1500     }
1501     if (ready.all()) {
1502       return Traits::FinalReturn(std::move(result0), std::move(result1),
1503                                  std::move(result2), std::move(result3),
1504                                  std::move(result4), std::move(result5),
1505                                  std::move(result6), std::move(result7));
1506     }
1507     return Pending{};
1508   }
1509 };
1510 
1511 template <class Traits, typename P0, typename P1, typename P2, typename P3,
1512           typename P4, typename P5, typename P6, typename P7, typename P8>
1513 struct JoinState<Traits, P0, P1, P2, P3, P4, P5, P6, P7, P8> {
1514   template <typename T>
1515   using UnwrappedType = decltype(Traits::Unwrapped(std::declval<T>()));
1516   using Promise0 = PromiseLike<P0>;
1517   using Result0 = UnwrappedType<typename Promise0::Result>;
1518   union {
1519     GPR_NO_UNIQUE_ADDRESS Promise0 promise0;
1520     GPR_NO_UNIQUE_ADDRESS Result0 result0;
1521   };
1522   using Promise1 = PromiseLike<P1>;
1523   using Result1 = UnwrappedType<typename Promise1::Result>;
1524   union {
1525     GPR_NO_UNIQUE_ADDRESS Promise1 promise1;
1526     GPR_NO_UNIQUE_ADDRESS Result1 result1;
1527   };
1528   using Promise2 = PromiseLike<P2>;
1529   using Result2 = UnwrappedType<typename Promise2::Result>;
1530   union {
1531     GPR_NO_UNIQUE_ADDRESS Promise2 promise2;
1532     GPR_NO_UNIQUE_ADDRESS Result2 result2;
1533   };
1534   using Promise3 = PromiseLike<P3>;
1535   using Result3 = UnwrappedType<typename Promise3::Result>;
1536   union {
1537     GPR_NO_UNIQUE_ADDRESS Promise3 promise3;
1538     GPR_NO_UNIQUE_ADDRESS Result3 result3;
1539   };
1540   using Promise4 = PromiseLike<P4>;
1541   using Result4 = UnwrappedType<typename Promise4::Result>;
1542   union {
1543     GPR_NO_UNIQUE_ADDRESS Promise4 promise4;
1544     GPR_NO_UNIQUE_ADDRESS Result4 result4;
1545   };
1546   using Promise5 = PromiseLike<P5>;
1547   using Result5 = UnwrappedType<typename Promise5::Result>;
1548   union {
1549     GPR_NO_UNIQUE_ADDRESS Promise5 promise5;
1550     GPR_NO_UNIQUE_ADDRESS Result5 result5;
1551   };
1552   using Promise6 = PromiseLike<P6>;
1553   using Result6 = UnwrappedType<typename Promise6::Result>;
1554   union {
1555     GPR_NO_UNIQUE_ADDRESS Promise6 promise6;
1556     GPR_NO_UNIQUE_ADDRESS Result6 result6;
1557   };
1558   using Promise7 = PromiseLike<P7>;
1559   using Result7 = UnwrappedType<typename Promise7::Result>;
1560   union {
1561     GPR_NO_UNIQUE_ADDRESS Promise7 promise7;
1562     GPR_NO_UNIQUE_ADDRESS Result7 result7;
1563   };
1564   using Promise8 = PromiseLike<P8>;
1565   using Result8 = UnwrappedType<typename Promise8::Result>;
1566   union {
1567     GPR_NO_UNIQUE_ADDRESS Promise8 promise8;
1568     GPR_NO_UNIQUE_ADDRESS Result8 result8;
1569   };
1570   GPR_NO_UNIQUE_ADDRESS BitSet<9> ready;
1571   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(P0&& p0, P1&& p1, P2&& p2,
1572                                                  P3&& p3, P4&& p4, P5&& p5,
1573                                                  P6&& p6, P7&& p7, P8&& p8) {
1574     Construct(&promise0, std::forward<P0>(p0));
1575     Construct(&promise1, std::forward<P1>(p1));
1576     Construct(&promise2, std::forward<P2>(p2));
1577     Construct(&promise3, std::forward<P3>(p3));
1578     Construct(&promise4, std::forward<P4>(p4));
1579     Construct(&promise5, std::forward<P5>(p5));
1580     Construct(&promise6, std::forward<P6>(p6));
1581     Construct(&promise7, std::forward<P7>(p7));
1582     Construct(&promise8, std::forward<P8>(p8));
1583   }
1584   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(const JoinState& other) {
1585     DCHECK(other.ready.none());
1586     Construct(&promise0, other.promise0);
1587     Construct(&promise1, other.promise1);
1588     Construct(&promise2, other.promise2);
1589     Construct(&promise3, other.promise3);
1590     Construct(&promise4, other.promise4);
1591     Construct(&promise5, other.promise5);
1592     Construct(&promise6, other.promise6);
1593     Construct(&promise7, other.promise7);
1594     Construct(&promise8, other.promise8);
1595   }
1596   JoinState& operator=(const JoinState& other) = delete;
1597   JoinState& operator=(JoinState&& other) = delete;
1598   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION JoinState(JoinState&& other) noexcept {
1599     DCHECK(other.ready.none());
1600     Construct(&promise0, std::move(other.promise0));
1601     Construct(&promise1, std::move(other.promise1));
1602     Construct(&promise2, std::move(other.promise2));
1603     Construct(&promise3, std::move(other.promise3));
1604     Construct(&promise4, std::move(other.promise4));
1605     Construct(&promise5, std::move(other.promise5));
1606     Construct(&promise6, std::move(other.promise6));
1607     Construct(&promise7, std::move(other.promise7));
1608     Construct(&promise8, std::move(other.promise8));
1609   }
1610   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION ~JoinState() {
1611     if (ready.is_set(0)) {
1612       Destruct(&result0);
1613     } else {
1614       Destruct(&promise0);
1615     }
1616     if (ready.is_set(1)) {
1617       Destruct(&result1);
1618     } else {
1619       Destruct(&promise1);
1620     }
1621     if (ready.is_set(2)) {
1622       Destruct(&result2);
1623     } else {
1624       Destruct(&promise2);
1625     }
1626     if (ready.is_set(3)) {
1627       Destruct(&result3);
1628     } else {
1629       Destruct(&promise3);
1630     }
1631     if (ready.is_set(4)) {
1632       Destruct(&result4);
1633     } else {
1634       Destruct(&promise4);
1635     }
1636     if (ready.is_set(5)) {
1637       Destruct(&result5);
1638     } else {
1639       Destruct(&promise5);
1640     }
1641     if (ready.is_set(6)) {
1642       Destruct(&result6);
1643     } else {
1644       Destruct(&promise6);
1645     }
1646     if (ready.is_set(7)) {
1647       Destruct(&result7);
1648     } else {
1649       Destruct(&promise7);
1650     }
1651     if (ready.is_set(8)) {
1652       Destruct(&result8);
1653     } else {
1654       Destruct(&promise8);
1655     }
1656   }
1657   using Result = typename Traits::template ResultType<
1658       std::tuple<Result0, Result1, Result2, Result3, Result4, Result5, Result6,
1659                  Result7, Result8>>;
1660   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Result> PollOnce() {
1661     if (!ready.is_set(0)) {
1662       GRPC_TRACE_VLOG(promise_primitives, 2)
1663           << "join[" << this << "]: begin poll joint 1/9";
1664       auto poll = promise0();
1665       GRPC_TRACE_VLOG(promise_primitives, 2)
1666           << "join[" << this << "]: end poll joint 1/9 "
1667           << (poll.pending()
1668                   ? "pending"
1669                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1670       if (auto* p = poll.value_if_ready()) {
1671         if (Traits::IsOk(*p)) {
1672           ready.set(0);
1673           Destruct(&promise0);
1674           Construct(&result0, Traits::Unwrapped(std::move(*p)));
1675         } else {
1676           return Traits::template EarlyReturn<Result>(std::move(*p));
1677         }
1678       }
1679     } else {
1680       GRPC_TRACE_VLOG(promise_primitives, 2)
1681           << "join[" << this << "]: joint 1/9 already ready";
1682     }
1683     if (!ready.is_set(1)) {
1684       GRPC_TRACE_VLOG(promise_primitives, 2)
1685           << "join[" << this << "]: begin poll joint 2/9";
1686       auto poll = promise1();
1687       GRPC_TRACE_VLOG(promise_primitives, 2)
1688           << "join[" << this << "]: end poll joint 2/9 "
1689           << (poll.pending()
1690                   ? "pending"
1691                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1692       if (auto* p = poll.value_if_ready()) {
1693         if (Traits::IsOk(*p)) {
1694           ready.set(1);
1695           Destruct(&promise1);
1696           Construct(&result1, Traits::Unwrapped(std::move(*p)));
1697         } else {
1698           return Traits::template EarlyReturn<Result>(std::move(*p));
1699         }
1700       }
1701     } else {
1702       GRPC_TRACE_VLOG(promise_primitives, 2)
1703           << "join[" << this << "]: joint 2/9 already ready";
1704     }
1705     if (!ready.is_set(2)) {
1706       GRPC_TRACE_VLOG(promise_primitives, 2)
1707           << "join[" << this << "]: begin poll joint 3/9";
1708       auto poll = promise2();
1709       GRPC_TRACE_VLOG(promise_primitives, 2)
1710           << "join[" << this << "]: end poll joint 3/9 "
1711           << (poll.pending()
1712                   ? "pending"
1713                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1714       if (auto* p = poll.value_if_ready()) {
1715         if (Traits::IsOk(*p)) {
1716           ready.set(2);
1717           Destruct(&promise2);
1718           Construct(&result2, Traits::Unwrapped(std::move(*p)));
1719         } else {
1720           return Traits::template EarlyReturn<Result>(std::move(*p));
1721         }
1722       }
1723     } else {
1724       GRPC_TRACE_VLOG(promise_primitives, 2)
1725           << "join[" << this << "]: joint 3/9 already ready";
1726     }
1727     if (!ready.is_set(3)) {
1728       GRPC_TRACE_VLOG(promise_primitives, 2)
1729           << "join[" << this << "]: begin poll joint 4/9";
1730       auto poll = promise3();
1731       GRPC_TRACE_VLOG(promise_primitives, 2)
1732           << "join[" << this << "]: end poll joint 4/9 "
1733           << (poll.pending()
1734                   ? "pending"
1735                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1736       if (auto* p = poll.value_if_ready()) {
1737         if (Traits::IsOk(*p)) {
1738           ready.set(3);
1739           Destruct(&promise3);
1740           Construct(&result3, Traits::Unwrapped(std::move(*p)));
1741         } else {
1742           return Traits::template EarlyReturn<Result>(std::move(*p));
1743         }
1744       }
1745     } else {
1746       GRPC_TRACE_VLOG(promise_primitives, 2)
1747           << "join[" << this << "]: joint 4/9 already ready";
1748     }
1749     if (!ready.is_set(4)) {
1750       GRPC_TRACE_VLOG(promise_primitives, 2)
1751           << "join[" << this << "]: begin poll joint 5/9";
1752       auto poll = promise4();
1753       GRPC_TRACE_VLOG(promise_primitives, 2)
1754           << "join[" << this << "]: end poll joint 5/9 "
1755           << (poll.pending()
1756                   ? "pending"
1757                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1758       if (auto* p = poll.value_if_ready()) {
1759         if (Traits::IsOk(*p)) {
1760           ready.set(4);
1761           Destruct(&promise4);
1762           Construct(&result4, Traits::Unwrapped(std::move(*p)));
1763         } else {
1764           return Traits::template EarlyReturn<Result>(std::move(*p));
1765         }
1766       }
1767     } else {
1768       GRPC_TRACE_VLOG(promise_primitives, 2)
1769           << "join[" << this << "]: joint 5/9 already ready";
1770     }
1771     if (!ready.is_set(5)) {
1772       GRPC_TRACE_VLOG(promise_primitives, 2)
1773           << "join[" << this << "]: begin poll joint 6/9";
1774       auto poll = promise5();
1775       GRPC_TRACE_VLOG(promise_primitives, 2)
1776           << "join[" << this << "]: end poll joint 6/9 "
1777           << (poll.pending()
1778                   ? "pending"
1779                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1780       if (auto* p = poll.value_if_ready()) {
1781         if (Traits::IsOk(*p)) {
1782           ready.set(5);
1783           Destruct(&promise5);
1784           Construct(&result5, Traits::Unwrapped(std::move(*p)));
1785         } else {
1786           return Traits::template EarlyReturn<Result>(std::move(*p));
1787         }
1788       }
1789     } else {
1790       GRPC_TRACE_VLOG(promise_primitives, 2)
1791           << "join[" << this << "]: joint 6/9 already ready";
1792     }
1793     if (!ready.is_set(6)) {
1794       GRPC_TRACE_VLOG(promise_primitives, 2)
1795           << "join[" << this << "]: begin poll joint 7/9";
1796       auto poll = promise6();
1797       GRPC_TRACE_VLOG(promise_primitives, 2)
1798           << "join[" << this << "]: end poll joint 7/9 "
1799           << (poll.pending()
1800                   ? "pending"
1801                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1802       if (auto* p = poll.value_if_ready()) {
1803         if (Traits::IsOk(*p)) {
1804           ready.set(6);
1805           Destruct(&promise6);
1806           Construct(&result6, Traits::Unwrapped(std::move(*p)));
1807         } else {
1808           return Traits::template EarlyReturn<Result>(std::move(*p));
1809         }
1810       }
1811     } else {
1812       GRPC_TRACE_VLOG(promise_primitives, 2)
1813           << "join[" << this << "]: joint 7/9 already ready";
1814     }
1815     if (!ready.is_set(7)) {
1816       GRPC_TRACE_VLOG(promise_primitives, 2)
1817           << "join[" << this << "]: begin poll joint 8/9";
1818       auto poll = promise7();
1819       GRPC_TRACE_VLOG(promise_primitives, 2)
1820           << "join[" << this << "]: end poll joint 8/9 "
1821           << (poll.pending()
1822                   ? "pending"
1823                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1824       if (auto* p = poll.value_if_ready()) {
1825         if (Traits::IsOk(*p)) {
1826           ready.set(7);
1827           Destruct(&promise7);
1828           Construct(&result7, Traits::Unwrapped(std::move(*p)));
1829         } else {
1830           return Traits::template EarlyReturn<Result>(std::move(*p));
1831         }
1832       }
1833     } else {
1834       GRPC_TRACE_VLOG(promise_primitives, 2)
1835           << "join[" << this << "]: joint 8/9 already ready";
1836     }
1837     if (!ready.is_set(8)) {
1838       GRPC_TRACE_VLOG(promise_primitives, 2)
1839           << "join[" << this << "]: begin poll joint 9/9";
1840       auto poll = promise8();
1841       GRPC_TRACE_VLOG(promise_primitives, 2)
1842           << "join[" << this << "]: end poll joint 9/9 "
1843           << (poll.pending()
1844                   ? "pending"
1845                   : (Traits::IsOk(poll.value()) ? "ready" : "early-error"));
1846       if (auto* p = poll.value_if_ready()) {
1847         if (Traits::IsOk(*p)) {
1848           ready.set(8);
1849           Destruct(&promise8);
1850           Construct(&result8, Traits::Unwrapped(std::move(*p)));
1851         } else {
1852           return Traits::template EarlyReturn<Result>(std::move(*p));
1853         }
1854       }
1855     } else {
1856       GRPC_TRACE_VLOG(promise_primitives, 2)
1857           << "join[" << this << "]: joint 9/9 already ready";
1858     }
1859     if (ready.all()) {
1860       return Traits::FinalReturn(
1861           std::move(result0), std::move(result1), std::move(result2),
1862           std::move(result3), std::move(result4), std::move(result5),
1863           std::move(result6), std::move(result7), std::move(result8));
1864     }
1865     return Pending{};
1866   }
1867 };
1868 
1869 }  // namespace promise_detail
1870 }  // namespace grpc_core
1871 
1872 #endif  // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_JOIN_STATE_H
1873