/*
 * Copyright (C) 2012 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.
 */

#ifndef ART_RUNTIME_THREAD_POOL_H_
#define ART_RUNTIME_THREAD_POOL_H_

#include <deque>
#include <functional>
#include <vector>

#include "barrier.h"
#include "base/macros.h"
#include "base/mem_map.h"
#include "base/mutex.h"

namespace art HIDDEN {

class AbstractThreadPool;

class Closure {
 public:
  virtual ~Closure() { }
  virtual void Run(Thread* self) = 0;
};

class FunctionClosure : public Closure {
 public:
  explicit FunctionClosure(std::function<void(Thread*)>&& f) : func_(std::move(f)) {}
  void Run(Thread* self) override {
    func_(self);
  }

 private:
  std::function<void(Thread*)> func_;
};

class Task : public Closure {
 public:
  // Called after Closure::Run has been called.
  virtual void Finalize() { }
};

class SelfDeletingTask : public Task {
 public:
  virtual ~SelfDeletingTask() { }
  virtual void Finalize() {
    delete this;
  }
};

class FunctionTask : public SelfDeletingTask {
 public:
  explicit FunctionTask(std::function<void(Thread*)>&& func) : func_(std::move(func)) {}

  void Run(Thread* self) override {
    func_(self);
  }

 private:
  std::function<void(Thread*)> func_;
};

class ThreadPoolWorker {
 public:
  static const size_t kDefaultStackSize = 1 * MB;

  size_t GetStackSize() const {
    DCHECK(stack_.IsValid());
    return stack_.Size();
  }

  virtual ~ThreadPoolWorker();

  // Set the "nice" priority for this worker.
  void SetPthreadPriority(int priority);

  // Get the "nice" priority for this worker.
  int GetPthreadPriority();

  Thread* GetThread() const { return thread_; }

 protected:
  ThreadPoolWorker(AbstractThreadPool* thread_pool, const std::string& name, size_t stack_size);
  static void* Callback(void* arg) REQUIRES(!Locks::mutator_lock_);
  virtual void Run();

  AbstractThreadPool* const thread_pool_;
  const std::string name_;
  MemMap stack_;
  pthread_t pthread_;
  Thread* thread_;

 private:
  friend class AbstractThreadPool;
  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorker);
};

// Note that thread pool workers will set Thread#setCanCallIntoJava to false.
class AbstractThreadPool {
 public:
  // Returns the number of threads in the thread pool.
  size_t GetThreadCount() const {
    return threads_.size();
  }

  EXPORT const std::vector<ThreadPoolWorker*>& GetWorkers();

  // Broadcast to the workers and tell them to empty out the work queue.
  EXPORT void StartWorkers(Thread* self) REQUIRES(!task_queue_lock_);

  // Do not allow workers to grab any new tasks.
  EXPORT void StopWorkers(Thread* self) REQUIRES(!task_queue_lock_);

  // Returns if the thread pool has started.
  bool HasStarted(Thread* self) REQUIRES(!task_queue_lock_);

  // Add a new task, the first available started worker will process it. Does not delete the task
  // after running it, it is the caller's responsibility.
  virtual void AddTask(Thread* self, Task* task) REQUIRES(!task_queue_lock_) = 0;

  // Remove all tasks in the queue.
  virtual void RemoveAllTasks(Thread* self) REQUIRES(!task_queue_lock_) = 0;

  virtual size_t GetTaskCount(Thread* self) REQUIRES(!task_queue_lock_) = 0;

  // Create the threads of this pool.
  EXPORT void CreateThreads();

  // Stops and deletes all threads in this pool.
  void DeleteThreads();

  // Wait for all tasks currently on queue to get completed. If the pool has been stopped, only
  // wait till all already running tasks are done.
  // When the pool was created with peers for workers, do_work must not be true (see ThreadPool()).
  EXPORT void Wait(Thread* self, bool do_work, bool may_hold_locks) REQUIRES(!task_queue_lock_);

  // Returns the total amount of workers waited for tasks.
  uint64_t GetWaitTime() const {
    return total_wait_time_;
  }

  // Provides a way to bound the maximum number of worker threads, threads must be less the the
  // thread count of the thread pool.
  void SetMaxActiveWorkers(size_t threads) REQUIRES(!task_queue_lock_);

  // Set the "nice" priority for threads in the pool.
  void SetPthreadPriority(int priority);

  // CHECK that the "nice" priority of threads in the pool is the given
  // `priority`.
  void CheckPthreadPriority(int priority);

  // Wait for workers to be created.
  void WaitForWorkersToBeCreated();

  virtual ~AbstractThreadPool() {}

 protected:
  // get a task to run, blocks if there are no tasks left
  Task* GetTask(Thread* self) REQUIRES(!task_queue_lock_);

  // Try to get a task, returning null if there is none available.
  Task* TryGetTask(Thread* self) REQUIRES(!task_queue_lock_);
  virtual Task* TryGetTaskLocked() REQUIRES(task_queue_lock_) = 0;

  // Are we shutting down?
  bool IsShuttingDown() const REQUIRES(task_queue_lock_) {
    return shutting_down_;
  }

  virtual bool HasOutstandingTasks() const REQUIRES(task_queue_lock_) = 0;

  EXPORT AbstractThreadPool(const char* name,
                            size_t num_threads,
                            bool create_peers,
                            size_t worker_stack_size);

  const std::string name_;
  Mutex task_queue_lock_;
  ConditionVariable task_queue_condition_ GUARDED_BY(task_queue_lock_);
  ConditionVariable completion_condition_ GUARDED_BY(task_queue_lock_);
  volatile bool started_ GUARDED_BY(task_queue_lock_);
  volatile bool shutting_down_ GUARDED_BY(task_queue_lock_);
  // How many worker threads are waiting on the condition.
  volatile size_t waiting_count_ GUARDED_BY(task_queue_lock_);
  std::vector<ThreadPoolWorker*> threads_;
  // Work balance detection.
  uint64_t start_time_ GUARDED_BY(task_queue_lock_);
  uint64_t total_wait_time_;
  Barrier creation_barier_;
  size_t max_active_workers_ GUARDED_BY(task_queue_lock_);
  const bool create_peers_;
  const size_t worker_stack_size_;

 private:
  friend class ThreadPoolWorker;
  friend class WorkStealingWorker;
  DISALLOW_COPY_AND_ASSIGN(AbstractThreadPool);
};

class EXPORT ThreadPool : public AbstractThreadPool {
 public:
  // Create a named thread pool with the given number of threads.
  //
  // If create_peers is true, all worker threads will have a Java peer object. Note that if the
  // pool is asked to do work on the current thread (see Wait), a peer may not be available. Wait
  // will conservatively abort if create_peers and do_work are true.
  static ThreadPool* Create(const char* name,
                            size_t num_threads,
                            bool create_peers = false,
                            size_t worker_stack_size = ThreadPoolWorker::kDefaultStackSize) {
    ThreadPool* pool = new ThreadPool(name, num_threads, create_peers, worker_stack_size);
    pool->CreateThreads();
    return pool;
  }

  void AddTask(Thread* self, Task* task) REQUIRES(!task_queue_lock_) override;
  size_t GetTaskCount(Thread* self) REQUIRES(!task_queue_lock_) override;
  void RemoveAllTasks(Thread* self) REQUIRES(!task_queue_lock_) override;
  ~ThreadPool() override;

 protected:
  Task* TryGetTaskLocked() REQUIRES(task_queue_lock_) override;

  bool HasOutstandingTasks() const REQUIRES(task_queue_lock_) override {
    return started_ && !tasks_.empty();
  }

  ThreadPool(const char* name,
             size_t num_threads,
             bool create_peers,
             size_t worker_stack_size)
      : AbstractThreadPool(name, num_threads, create_peers, worker_stack_size) {}

 private:
  std::deque<Task*> tasks_ GUARDED_BY(task_queue_lock_);

  DISALLOW_COPY_AND_ASSIGN(ThreadPool);
};

}  // namespace art

#endif  // ART_RUNTIME_THREAD_POOL_H_
