// File: amukherj[P]concurrencyts/./future.h
// Function: concurrencyts::future<concurrencyts::when_any_result<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_any<__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_any(InputIt begin, InputIt end)
  -> future<when_any_result<
      std::vector<typename std::iterator_traits<InputIt>::value_type>
  >> {

  using ret_type = when_any_result<
    std::vector<typename std::iterator_traits<InputIt>::value_type>>;
  ret_type result_value;

  struct _sync_context {
    std::mutex mtx;
    std::condition_variable found, start;
    bool done, startCheck;
    promise<ret_type> prom;

    _sync_context() : done(false), startCheck(false) {}
  };
  auto context = std::make_shared<_sync_context>();
  auto result = context->prom.get_future();

  if (begin == end) {
    context->prom.set(make_when_any_result(-1, begin, end));
    return result;
  }

  std::thread thr([begin, end, context]() {
    std::unique_lock<std::mutex> ul{context->mtx};
    context->startCheck = true;
    context->start.notify_one();
    while (!context->done) {
      context->found.wait(ul);

      // main thread found one already
      if (context->done) {
        return;
      }

      for (auto it = begin; it != end; ++it) {
        if (it->is_ready()) {
          context->prom.set(make_when_any_result(std::distance(begin, it),
            begin, end));
          break;
        }
      }
    }
  });
  thr.detach();

  std::unique_lock<std::mutex> ul{context->mtx};
  context->start.wait(ul, [context]()->bool {return context->startCheck;});
  for (auto it = begin; it != end; ++it) {
    if (it->is_ready()) {
      context->done = true;
      context->found.notify_one();
      context->prom.set(make_when_any_result(std::distance(begin, it),
        begin, end));
      break;
    } else {
      it->await(context->found);
    }
  }

  return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x130(%rbp)
movq %rdi, %rax
movq %rax, -0x128(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x115b0
leaq -0x48(%rbp), %rdi
callq 0x115d0
jmp 0xb2fc
movb $0x0, -0x55(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x11640
movq -0x130(%rbp), %rdi
movq %rax, %rsi
addq $0x90, %rsi
callq 0x11660
jmp 0xb321
leaq -0x10(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0x116d0
testb $0x1, %al
jne 0xb337
jmp 0xb3f8
leaq -0x48(%rbp), %rdi
callq 0x11640
addq $0x90, %rax
movq %rax, -0x138(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rdx
movq -0x88(%rbp), %rcx
leaq -0x78(%rbp), %rdi
movq $-0x1, %rsi
callq 0x11740
jmp 0xb37d
movq -0x138(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x11710
jmp 0xb38f
leaq -0x78(%rbp), %rdi
callq 0xb7e0
movb $0x1, -0x55(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0xb6ed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xb736
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xb72d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xb721
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x78(%rbp), %rdi
callq 0xb7e0
jmp 0xb721
movq -0x10(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x11800
leaq -0x98(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x11830
jmp 0xb433
leaq -0xb8(%rbp), %rdi
callq 0x118f0
leaq -0x98(%rbp), %rdi
callq 0x32c0
jmp 0xb44d
leaq -0x48(%rbp), %rdi
callq 0x11640
movq %rax, %rsi
leaq -0xc8(%rbp), %rdi
callq 0xc290
jmp 0xb467
leaq -0x48(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x11640
movq -0x150(%rbp), %rsi
addq $0x58, %rax
movq %rax, -0x148(%rbp)
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0x11800
movq -0x148(%rbp), %rdi
movq -0x140(%rbp), %rdx
leaq -0xc8(%rbp), %rsi
callq 0x11910
jmp 0xb4b8
leaq -0xd8(%rbp), %rdi
callq 0x11960
movq -0x10(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0xb190
testb $0x1, %al
jne 0xb4e8
jmp 0xb6ab
leaq -0xe0(%rbp), %rdi
callq 0xfb90
movq %rax, %rdi
callq 0x11980
movb %al, -0x151(%rbp)
jmp 0xb504
movb -0x151(%rbp), %al
testb $0x1, %al
jne 0xb513
jmp 0xb665
leaq -0x48(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0x11640
movq -0x170(%rbp), %rdi
movb $0x1, 0x88(%rax)
callq 0x11640
movq %rax, %rdi
addq $0x28, %rdi
callq 0x30d0
movq -0x170(%rbp), %rdi
callq 0x11640
addq $0x90, %rax
movq %rax, -0x168(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x108(%rbp), %rdi
movq -0x110(%rbp), %rsi
callq 0x119b0
movq %rax, -0x160(%rbp)
jmp 0xb590
movq -0x160(%rbp), %rsi
movq -0x10(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x120(%rbp)
movq -0x118(%rbp), %rdx
movq -0x120(%rbp), %rcx
leaq -0x100(%rbp), %rdi
callq 0x11740
jmp 0xb5c9
movq -0x168(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x11710
jmp 0xb5de
leaq -0x100(%rbp), %rdi
callq 0xb7e0
jmp 0xb6ab
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x118f0
jmp 0xb721
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xb6df
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x11960
jmp 0xb6d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xb6d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x100(%rbp), %rdi
callq 0xb7e0
jmp 0xb6d3
leaq -0xe0(%rbp), %rdi
callq 0xfb90
movq %rax, -0x178(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x11640
movq -0x178(%rbp), %rdi
movq %rax, %rsi
addq $0x28, %rsi
callq 0x119f0
jmp 0xb696
jmp 0xb698
jmp 0xb69a
leaq -0xe0(%rbp), %rdi
callq 0xb220
jmp 0xb4cf
movb $0x1, -0x55(%rbp)
movl $0x1, -0x8c(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0xc380
leaq -0x98(%rbp), %rdi
callq 0xad90
jmp 0xb6ed
leaq -0xc8(%rbp), %rdi
callq 0xc380
leaq -0x98(%rbp), %rdi
callq 0xad90
jmp 0xb721
testb $0x1, -0x55(%rbp)
jne 0xb6ff
movq -0x130(%rbp), %rdi
callq 0xb800
leaq -0x48(%rbp), %rdi
callq 0x11a20
leaq -0x38(%rbp), %rdi
callq 0xb7e0
movq -0x128(%rbp), %rax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
movq -0x130(%rbp), %rdi
callq 0xb800
leaq -0x48(%rbp), %rdi
callq 0x11a20
leaq -0x38(%rbp), %rdi
callq 0xb7e0
movq -0x50(%rbp), %rdi
callq 0x32d0
nopl (%rax,%rax)