// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Dmitry Vyukov <dvyukov@google.com>
// Copyright (C) 2016 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_USE_THREADS
// clang-format off
#include "main.h"
#include "Eigen/ThreadPool"
// clang-format on

#include <atomic>
#include <chrono>
#include <functional>
#include <thread>

// Spin-wait with yielding until the condition is met, or fail after a timeout.
// Returns true if the condition was met before the deadline.
template <typename Cond>
static bool spin_wait(Cond cond, int timeout_seconds = 60) {
  auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout_seconds);
  while (!cond()) {
    if (std::chrono::steady_clock::now() > deadline) return false;
    std::this_thread::yield();
  }
  return true;
}

static void test_create_destroy_empty_pool() {
  // Just create and destroy the pool. This will wind up and tear down worker
  // threads. Ensure there are no issues in that logic.
  for (int i = 0; i < 16; ++i) {
    ThreadPool tp(i);
  }
}

static thread_local bool delaying_environment_worker = false;

struct DelayingThreadEnvironment {
  using EnvThread = StlThreadEnvironment::EnvThread;

  struct Task {
    std::function<void()> f;
    Task() = default;
    Task(Task&&) = default;
    Task& operator=(Task&& other) {
      f = std::move(other.f);
      // Widen the interval between taking a task and retiring the worker's
      // spinner.
      if (f && delaying_environment_worker)
        std::this_thread::sleep_for(std::chrono::microseconds(100));
      return *this;
    }
  };

  EnvThread* CreateThread(std::function<void()> f) {
    return new EnvThread([f = std::move(f)]() {
      delaying_environment_worker = true;
      f();
    });
  }
  Task CreateTask(std::function<void()> f) {
    Task task;
    task.f = std::move(f);
    return task;
  }
  void ExecuteTask(const Task& task) { task.f(); }
};

template <typename Environment = StlThreadEnvironment>
static void test_parallelism(bool allow_spinning, int kThreads = 16) {
  // Test we never-ever fail to match available tasks with idle threads.
  // The phases below require a multiple of four threads.
  ThreadPoolTempl<Environment> tp(kThreads, allow_spinning);
  VERIFY_IS_EQUAL(tp.NumThreads(), kThreads);
  VERIFY_IS_EQUAL(tp.CurrentThreadId(), -1);
  for (int iter = 0; iter < 100; ++iter) {
    std::atomic<int> running(0);
    std::atomic<int> done(0);
    std::atomic<int> phase(0);
    // Schedule kThreads tasks and ensure that they all are running.
    for (int i = 0; i < kThreads; ++i) {
      tp.Schedule([&]() {
        const int thread_id = tp.CurrentThreadId();
        VERIFY_GE(thread_id, 0);
        VERIFY_LE(thread_id, kThreads - 1);
        running++;
        while (phase < 1) {
          std::this_thread::yield();
        }
        done++;
      });
    }
    VERIFY(spin_wait([&] { return running == kThreads; }));
    running = 0;
    phase = 1;
    // Now, while the previous tasks exit, schedule another kThreads tasks and
    // ensure that they are running.
    for (int i = 0; i < kThreads; ++i) {
      tp.Schedule([&, i]() {
        running++;
        while (phase < 2) {
          std::this_thread::yield();
        }
        // When all tasks are running, half of tasks exit, quarter of tasks
        // continue running and quarter of tasks schedule another 2 tasks each.
        // Concurrently main thread schedules another quarter of tasks.
        // This gives us another kThreads tasks and we ensure that they all
        // are running.
        if (i < kThreads / 2) {
        } else if (i < 3 * kThreads / 4) {
          running++;
          while (phase < 3) {
            std::this_thread::yield();
          }
          done++;
        } else {
          for (int j = 0; j < 2; ++j) {
            tp.Schedule([&]() {
              running++;
              while (phase < 3) {
                std::this_thread::yield();
              }
              done++;
            });
          }
        }
        done++;
      });
    }
    VERIFY(spin_wait([&] { return running == kThreads; }));
    running = 0;
    phase = 2;
    for (int i = 0; i < kThreads / 4; ++i) {
      tp.Schedule([&]() {
        running++;
        while (phase < 3) {
          std::this_thread::yield();
        }
        done++;
      });
    }
    VERIFY(spin_wait([&] { return running == kThreads; }));
    phase = 3;
    VERIFY(spin_wait([&] { return done == 3 * kThreads; }));
  }
}

static void test_cancel() {
  ThreadPool tp(2);

  // Schedule a large number of closure that each sleeps for one second. This
  // will keep the thread pool busy for much longer than the default test timeout.
  for (int i = 0; i < 1000; ++i) {
    tp.Schedule([]() { std::this_thread::sleep_for(std::chrono::milliseconds(2000)); });
  }

  // Cancel the processing of all the closures that are still pending.
  tp.Cancel();
}

static void test_pool_partitions() {
  const int kThreads = 2;

  std::atomic<int> running(0);
  std::atomic<int> done(0);
  std::atomic<int> phase(0);

  {
    ThreadPool tp(kThreads);

    // Assign each thread to its own partition, so that stealing other work only
    // occurs globally when a thread is idle.
    std::vector<std::pair<unsigned, unsigned>> steal_partitions(kThreads);
    for (int i = 0; i < kThreads; ++i) {
      steal_partitions[i] = std::make_pair(i, i + 1);
    }
    tp.SetStealPartitions(steal_partitions);

    // Schedule kThreads tasks and ensure that they all are running.
    for (int i = 0; i < kThreads; ++i) {
      tp.Schedule([&]() {
        const int thread_id = tp.CurrentThreadId();
        VERIFY_GE(thread_id, 0);
        VERIFY_LE(thread_id, kThreads - 1);
        ++running;
        while (phase < 1) {
          std::this_thread::yield();
        }
        ++done;
      });
    }
    VERIFY(spin_wait([&] { return running == kThreads; }));
    // Schedule each closure to only run on thread 'i' and verify that it does.
    for (int i = 0; i < kThreads; ++i) {
      tp.ScheduleWithHint(
          [&, i]() {
            ++running;
            const int thread_id = tp.CurrentThreadId();
            VERIFY_IS_EQUAL(thread_id, i);
            while (phase < 2) {
              std::this_thread::yield();
            }
            ++done;
          },
          i, i + 1);
    }
    running = 0;
    phase = 1;
    VERIFY(spin_wait([&] { return running == kThreads; }));
    running = 0;
    phase = 2;
  }
}

EIGEN_DECLARE_TEST(cxx11_non_blocking_thread_pool) {
  CALL_SUBTEST(test_parallelism<DelayingThreadEnvironment>(true, 4));
  CALL_SUBTEST(test_create_destroy_empty_pool());
  CALL_SUBTEST(test_parallelism(true));
  CALL_SUBTEST(test_parallelism(false));
  CALL_SUBTEST(test_cancel());
  CALL_SUBTEST(test_pool_partitions());
}
