// File: amukherj[P]concurrencyts/./future.h
// Function: concurrencyts::future<std::vector<std::iterator_traits<__gnu_cxx::__normal_iterator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>*, std::vector<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>>::value_type, std::allocator<std::iterator_traits<__gnu_cxx::__normal_iterator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>*, std::vector<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>>::value_type>>> concurrencyts::when_all<__gnu_cxx::__normal_iterator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>*, std::vector<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>>(__gnu_cxx::__normal_iterator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>*, std::vector<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>, __gnu_cxx::__normal_iterator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>*, std::vector<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<concurrencyts::future<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>)
auto when_all(InputIt begin, InputIt end)
  -> future<std::vector<typename std::iterator_traits<InputIt>::value_type>> {
  using ret_type = typename std::iterator_traits<InputIt>::value_type;
  promise<std::vector<ret_type>> prom;
  auto fut = prom.get_future();

  if (begin != end) {
    begin->wait();
    (begin + 1)->wait();
  }

  std::thread t([begin, end](promise<std::vector<ret_type>> prom) {
    try {
      std::vector<ret_type> result;
      begin->wait();
      (begin + 1)->wait();
      for (auto it = begin; it != end; ++it) {
        it->wait();
        result.emplace_back(std::move(*it));
      }
      prom.set(std::move(result));
      std::this_thread::sleep_for(std::chrono::seconds(5));
    } catch(std::exception& e) {
      prom.set_exception(e);
    }
  }, std::move(prom));
  t.detach();

  return fut;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x70(%rbp)
movq %rdi, %rax
movq %rax, -0x78(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
leaq -0x28(%rbp), %rdi
movq %rdi, -0x68(%rbp)
callq 0xfb00
movq -0x70(%rbp), %rdi
movq -0x68(%rbp), %rsi
movb $0x0, -0x29(%rbp)
callq 0xfb20
jmp 0xafc2
leaq -0x10(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0xb190
testb $0x1, %al
jne 0xafd5
jmp 0xb02e
leaq -0x10(%rbp), %rdi
callq 0xfb90
movq %rax, %rdi
callq 0xfbb0
jmp 0xafe8
leaq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0xfbe0
movq %rax, -0x48(%rbp)
leaq -0x48(%rbp), %rdi
callq 0xfb90
movq %rax, %rdi
callq 0xfbb0
jmp 0xb00d
jmp 0xb02e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xb0b0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xb0a7
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x28(%rbp), %rdx
callq 0xfc20
jmp 0xb051
leaq -0x50(%rbp), %rdi
callq 0x32c0
jmp 0xb05c
movb $0x1, -0x29(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xad90
testb $0x1, -0x29(%rbp)
jne 0xb091
jmp 0xb088
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xad90
jmp 0xb0a7
movq -0x70(%rbp), %rdi
callq 0xb2a0
leaq -0x28(%rbp), %rdi
callq 0xfce0
movq -0x78(%rbp), %rax
addq $0x80, %rsp
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0xb2a0
leaq -0x28(%rbp), %rdi
callq 0xfce0
movq -0x38(%rbp), %rdi
callq 0x32d0
nopw %cs:(%rax,%rax)
nopl (%rax)