// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_THREAD_POOL_H_
#define RUNTIME_VM_THREAD_POOL_H_

#include <memory>
#include <utility>

#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/os_thread.h"

namespace dart {

class ThreadPool {
 public:
  // Subclasses of Task are able to run on a ThreadPool.
  class Task {
   protected:
    Task();

   public:
    virtual ~Task();

    // Override this to provide task-specific behavior.
    virtual void Run() = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Task);
  };

  ThreadPool();

  // Shuts down this thread pool. Causes workers to terminate
  // themselves when they are active again.
  ~ThreadPool();

  // Runs a task on the thread pool.
  template <typename T, typename... Args>
  bool Run(Args&&... args) {
    return RunImpl(std::unique_ptr<Task>(new T(std::forward<Args>(args)...)));
  }

  // Some simple stats.
  uint64_t workers_running() const { return count_running_; }
  uint64_t workers_idle() const { return count_idle_; }
  uint64_t workers_started() const { return count_started_; }
  uint64_t workers_stopped() const { return count_stopped_; }

 private:
  class Worker {
   public:
    explicit Worker(ThreadPool* pool);

    // Sets a task on the worker.
    void SetTask(std::unique_ptr<Task> task);

    // Starts the thread for the worker.  This should only be called
    // after a task has been set by the initial call to SetTask().
    void StartThread();

    // Main loop for a worker. Returns true if worker is removed from thread
    // lists, false otherwise.
    bool Loop();

    // Causes worker to terminate eventually.
    void Shutdown();

    // Get the Worker's thread id.
    ThreadId id();

   private:
    friend class ThreadPool;

    // The main entry point for new worker threads.
    static void Main(uword args);

    bool IsDone() const { return done_; }

    // Fields owned by Worker.
    Monitor monitor_;
    ThreadPool* pool_;
    std::unique_ptr<Task> task_;
    ThreadId id_;
    bool done_;

    // Fields owned by ThreadPool.  Workers should not look at these
    // directly.  It's like looking at the sun.
    bool owned_;         // Protected by ThreadPool::mutex_
    Worker* all_next_;   // Protected by ThreadPool::mutex_
    Worker* idle_next_;  // Protected by ThreadPool::mutex_

    Worker* shutdown_next_;  // Protected by ThreadPool::exit_monitor

    DISALLOW_COPY_AND_ASSIGN(Worker);
  };

  class JoinList {
   public:
    explicit JoinList(ThreadJoinId id, JoinList* next) : id_(id), next_(next) {}

    // The thread pool's mutex_ must be held when calling this.
    static void AddLocked(ThreadJoinId id, JoinList** list);

    static void Join(JoinList** list);

    ThreadJoinId id() const { return id_; }
    JoinList* next() const { return next_; }

   private:
    ThreadJoinId id_;
    JoinList* next_;

    DISALLOW_COPY_AND_ASSIGN(JoinList);
  };

  bool RunImpl(std::unique_ptr<Task> task);
  void Shutdown();

  // Expensive.  Use only in assertions.
  bool IsIdle(Worker* worker);

  bool RemoveWorkerFromIdleList(Worker* worker);
  bool RemoveWorkerFromAllList(Worker* worker);

  void AddWorkerToShutdownList(Worker* worker);
  bool RemoveWorkerFromShutdownList(Worker* worker);

  void ReapExitedIdleThreads();

  // Worker operations.
  void SetIdleLocked(Worker* worker);  // Assumes mutex_ is held.
  void SetIdleAndReapExited(Worker* worker);
  bool ReleaseIdleWorker(Worker* worker);

  Mutex mutex_;
  bool shutting_down_;
  Worker* all_workers_;
  Worker* idle_workers_;
  uint64_t count_started_;
  uint64_t count_stopped_;
  uint64_t count_running_;
  uint64_t count_idle_;

  Monitor exit_monitor_;
  Worker* shutting_down_workers_;
  JoinList* join_list_;

  DISALLOW_COPY_AND_ASSIGN(ThreadPool);
};

}  // namespace dart

#endif  // RUNTIME_VM_THREAD_POOL_H_
