void addToThenChainOrExecute()

in dispenso/detail/future_impl.h [266:298]


  void addToThenChainOrExecute(SomeFutureImpl* impl, Schedulable& sched, std::launch asyncPolicy) {
    if (status_.intrusiveStatus().load(std::memory_order_acquire) == kReady) {
      if ((asyncPolicy & std::launch::async) == std::launch::async) {
        sched.schedule(OnceFunction(impl, true), ForceQueuingTag());
      } else {
        sched.schedule(OnceFunction(impl, true));
      }
      return;
    }

    constexpr size_t kImplSize = nextPow2(sizeof(ThenChain));
    auto* buffer = allocSmallBuffer<kImplSize>();
    ThenChain* link = reinterpret_cast<ThenChain*>(buffer);
    link->impl = impl;
    using NonConstSchedulable = std::remove_const_t<Schedulable>;
    NonConstSchedulable* nonConstSched = const_cast<NonConstSchedulable*>(&sched);
    link->schedulable = nonConstSched;
    if ((asyncPolicy & std::launch::async) == std::launch::async) {
      link->invoke = thenChainInvokeAsync<SomeFutureImpl, Schedulable>;
    } else {
      link->invoke = thenChainInvoke<SomeFutureImpl, Schedulable>;
    }
    link->next = thenChain_.load(std::memory_order_acquire);
    while (!thenChain_.compare_exchange_weak(link->next, link, std::memory_order_acq_rel)) {
    }

    // Okay, one last thing.  It is possible that we added to the thenChain just after
    // tryExecuteThenChain was called from run(). We still need to ensure that this work is kicked
    // off, so just double check here, and execute if that may have happened.
    if (status_.intrusiveStatus().load(std::memory_order_acquire) == kReady) {
      tryExecuteThenChain();
    }
  }