//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03, c++11, c++14, c++17

// ~stop_callback();

#include <atomic>
#include <cassert>
#include <chrono>
#include <functional>
#include <memory>
#include <optional>
#include <stop_token>
#include <type_traits>
#include <utility>
#include <vector>

#include "make_test_thread.h"
#include "test_macros.h"

struct CallbackHolder;

struct DeleteHolder {
  CallbackHolder& holder_;
  void operator()() const;
};

struct CallbackHolder {
  std::unique_ptr<std::stop_callback<DeleteHolder>> callback_;
};

void DeleteHolder::operator()() const { holder_.callback_.reset(); }

int main(int, char**) {
  // Unregisters the callback from the owned stop state, if any
  {
    std::stop_source ss;
    bool called = false;

    {
      std::stop_callback sc(ss.get_token(), [&] { called = true; });
    }
    ss.request_stop();
    assert(!called);
  }

  // The destructor does not block waiting for the execution of another
  // callback registered by an associated stop_callback.
  {
    std::stop_source ss;

    std::atomic<int> startedIndex    = 0;
    std::atomic<bool> callbackFinish = false;

    std::optional<std::stop_callback<std::function<void()>>> sc1(std::in_place, ss.get_token(), [&] {
      startedIndex = 1;
      startedIndex.notify_all();
      callbackFinish.wait(false);
    });

    std::optional<std::stop_callback<std::function<void()>>> sc2(std::in_place, ss.get_token(), [&] {
      startedIndex = 2;
      startedIndex.notify_all();
      callbackFinish.wait(false);
    });

    auto thread = support::make_test_thread([&] { ss.request_stop(); });

    startedIndex.wait(0);

    // now one of the callback has started but not finished.
    if (startedIndex == 1) {
      sc2.reset();   // destructor should not block
    } else if (startedIndex == 2) {
      sc1.reset();   // destructor should not block
    } else {
      assert(false); // something is wrong
    }

    callbackFinish = true;
    callbackFinish.notify_all();
    thread.join();
  }

  // If callback is concurrently executing on another thread, then the
  // return from the invocation of callback strongly happens before ([intro.races])
  // callback is destroyed.
  {
    struct Callback {
      std::atomic<bool>& started_;
      std::atomic<bool>& waitDone_;
      std::atomic<bool>& finished_;
      bool moved = false;

      Callback(std::atomic<bool>& started, std::atomic<bool>& waitDone, std::atomic<bool>& finished)
          : started_(started), waitDone_(waitDone), finished_(finished) {}
      Callback(Callback&& other) : started_(other.started_), waitDone_(other.waitDone_), finished_(other.finished_) {
        other.moved = true;
      }

      void operator()() const {
        struct ScopedGuard {
          std::atomic<bool>& g_finished_;
          ~ScopedGuard() { g_finished_.store(true, std::memory_order_relaxed); }
        };

        started_ = true;
        started_.notify_all();
        waitDone_.wait(false);
        ScopedGuard g{finished_};
      }

      ~Callback() {
        if (!moved) {
          // destructor has to be called after operator() returns
          assert(finished_.load(std::memory_order_relaxed));
        }
      }
    };

    std::stop_source ss;

    std::atomic<bool> started  = false;
    std::atomic<bool> waitDone = false;
    std::atomic<bool> finished = false;

    std::optional<std::stop_callback<Callback>> sc{
        std::in_place, ss.get_token(), Callback{started, waitDone, finished}};

    auto thread1 = support::make_test_thread([&] { ss.request_stop(); });
    started.wait(false);

    auto thread2 = support::make_test_thread([&] {
      using namespace std::chrono_literals;
      std::this_thread::sleep_for(1ms);
      waitDone = true;
      waitDone.notify_all();
    });

    sc.reset(); // destructor should block until operator() returns, i.e. waitDone to be true

    thread1.join();
    thread2.join();
  }

  // If callback is executing on the current thread, then the destructor does not block ([defns.block])
  // waiting for the return from the invocation of callback.
  {
    std::stop_source ss;

    CallbackHolder holder;
    holder.callback_ = std::make_unique<std::stop_callback<DeleteHolder>>(ss.get_token(), DeleteHolder{holder});

    assert(holder.callback_ != nullptr);

    ss.request_stop(); // the callbacks deletes itself. if the destructor blocks, it would be deadlock
    assert(holder.callback_ == nullptr);
  }

  return 0;
}
