/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "task_processor.h"
#include "base/time_utils.h"
#include "common_runtime_test.h"
#include "thread-current-inl.h"
#include "thread_pool.h"

namespace art HIDDEN {
namespace gc {

class TaskProcessorTest : public CommonRuntimeTest {
 public:
};

class RecursiveTask : public HeapTask {
 public:
  RecursiveTask(TaskProcessor* task_processor, Atomic<size_t>* counter, size_t max_recursion)
     : HeapTask(NanoTime() + MsToNs(10)), task_processor_(task_processor), counter_(counter),
       max_recursion_(max_recursion) {
  }
  void Run(Thread* self) override {
    if (max_recursion_ > 0) {
      task_processor_->AddTask(self,
                               new RecursiveTask(task_processor_, counter_, max_recursion_ - 1));
      counter_->fetch_add(1U, std::memory_order_seq_cst);
    }
  }

 private:
  TaskProcessor* const task_processor_;
  Atomic<size_t>* const counter_;
  const size_t max_recursion_;
};

class WorkUntilDoneTask : public SelfDeletingTask {
 public:
  WorkUntilDoneTask(TaskProcessor* task_processor, Atomic<bool>* done_running)
      : task_processor_(task_processor), done_running_(done_running) {
  }
  void Run(Thread* self) override {
    task_processor_->RunAllTasks(self);
    done_running_->store(true, std::memory_order_seq_cst);
  }

 private:
  TaskProcessor* const task_processor_;
  Atomic<bool>* done_running_;
};

TEST_F(TaskProcessorTest, Interrupt) {
  std::unique_ptr<ThreadPool> thread_pool(ThreadPool::Create("task processor test", 1U));
  Thread* const self = Thread::Current();
  TaskProcessor task_processor;
  static constexpr size_t kRecursion = 10;
  Atomic<bool> done_running(false);
  Atomic<size_t> counter(0);
  task_processor.AddTask(self, new RecursiveTask(&task_processor, &counter, kRecursion));
  task_processor.Start(self);
  // Add a task which will wait until interrupted to the thread pool.
  thread_pool->AddTask(self, new WorkUntilDoneTask(&task_processor, &done_running));
  thread_pool->StartWorkers(self);
  ASSERT_FALSE(done_running);
  // Wait until all the tasks are done, but since we didn't interrupt, done_running should be 0.
  while (counter.load(std::memory_order_seq_cst) != kRecursion) {
    usleep(10);
  }
  ASSERT_FALSE(done_running);
  task_processor.Stop(self);
  thread_pool->Wait(self, true, false);
  // After the interrupt and wait, the WorkUntilInterruptedTasktask should have terminated and
  // set done_running_ to true.
  ASSERT_TRUE(done_running.load(std::memory_order_seq_cst));

  // Test that we finish remaining tasks before returning from RunTasksUntilInterrupted.
  counter.store(0, std::memory_order_seq_cst);
  done_running.store(false, std::memory_order_seq_cst);
  // Self interrupt before any of the other tasks run, but since we added them we should keep on
  // working until all the tasks are completed.
  task_processor.Stop(self);
  task_processor.AddTask(self, new RecursiveTask(&task_processor, &counter, kRecursion));
  thread_pool->AddTask(self, new WorkUntilDoneTask(&task_processor, &done_running));
  thread_pool->StartWorkers(self);
  thread_pool->Wait(self, true, false);
  ASSERT_TRUE(done_running.load(std::memory_order_seq_cst));
  ASSERT_EQ(counter.load(std::memory_order_seq_cst), kRecursion);
}

class TestOrderTask : public HeapTask {
 public:
  TestOrderTask(uint64_t expected_time, size_t expected_counter, size_t* counter)
     : HeapTask(expected_time), expected_counter_(expected_counter), counter_(counter) {
  }
  void Run([[maybe_unused]] Thread* thread) override {
    ASSERT_EQ(*counter_, expected_counter_);
    ++*counter_;
  }

 private:
  const size_t expected_counter_;
  size_t* const counter_;
};

TEST_F(TaskProcessorTest, Ordering) {
  static const size_t kNumTasks = 25;
  const uint64_t current_time = NanoTime();
  Thread* const self = Thread::Current();
  TaskProcessor task_processor;
  task_processor.Stop(self);
  size_t counter = 0;
  std::vector<std::pair<uint64_t, size_t>> orderings;
  for (size_t i = 0; i < kNumTasks; ++i) {
    orderings.push_back(std::make_pair(current_time + MsToNs(10U * i), i));
  }
  for (size_t i = 0; i < kNumTasks; ++i) {
    std::swap(orderings[i], orderings[(i * 87654231 + 12345) % orderings.size()]);
  }
  for (const auto& pair : orderings) {
    auto* task = new TestOrderTask(pair.first, pair.second, &counter);
    task_processor.AddTask(self, task);
  }
  std::unique_ptr<ThreadPool> thread_pool(ThreadPool::Create("task processor test", 1U));
  Atomic<bool> done_running(false);
  // Add a task which will wait until interrupted to the thread pool.
  thread_pool->AddTask(self, new WorkUntilDoneTask(&task_processor, &done_running));
  ASSERT_FALSE(done_running.load(std::memory_order_seq_cst));
  thread_pool->StartWorkers(self);
  thread_pool->Wait(self, true, false);
  ASSERT_TRUE(done_running.load(std::memory_order_seq_cst));
  ASSERT_EQ(counter, kNumTasks);
}

}  // namespace gc
}  // namespace art
