// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/shared/worker_pool.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/shared/logging/logging.h"

namespace debug_ipc {

namespace {

// Useful for logging.
auto Preamble() { return std::this_thread::get_id(); }

// Unlocks on constructor, locks on destructor.
class UnlockGuard {
 public:
  using LockType = std::unique_lock<std::mutex>;

  UnlockGuard(LockType& lock) : lock_(&lock) {
    FX_DCHECK(lock_->owns_lock());
    lock_->unlock();
  }

  ~UnlockGuard() {
    FX_DCHECK(!lock_->owns_lock());
    lock_->lock();
  }

  FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(UnlockGuard);

 private:
  LockType* lock_;  // Not owning. Must outlive.
};

}  // namespace

class WorkerPool::Worker {
 public:
  Worker(WorkerPool* pool) : owning_pool_(pool) {}

  void Run() {
    FX_DCHECK(owning_pool_);
    FX_DCHECK(!thread_.joinable());  // Unstarted threads are not joinable.
    thread_ = std::thread(&WorkerPool::ThreadLoop, owning_pool_);
  }

  void Join() {
    if (thread_.joinable())
      thread_.join();
  }

 private:
  // We can have a back ref because the queue owns this object.
  WorkerPool* owning_pool_ = nullptr;
  std::thread thread_;
};

WorkerPool::WorkerPool(int max_workers, Observer* observer)
    : max_workers_(max_workers), observer_(observer) {}

WorkerPool::~WorkerPool() { Shutdown(); }

bool WorkerPool::PostTask(Task&& task) {
  {
    std::unique_lock<std::mutex> lock(mutex_);
    if (shutting_down_)
      return false;

    tasks_.push_back(std::move(task));

    if (!running_)
      return true;

    if (ShouldCreateWorker()) {
      CreateWorker(&lock);
      return true;
    }
  }

  SignalWork();
  return true;
}

void WorkerPool::Run() {
  DEBUG_LOG(WorkerPool) << Preamble() << " Running the queue.";
  {
    std::unique_lock<std::mutex> lock(mutex_);
    if (running_)
      return;
    running_ = true;

    // If there are no posted tasks, there is nothing to do yet.
    if (tasks_.empty())
      return;

    // If there are no available workers, we create a first one.
    if (ShouldCreateWorker()) {
      CreateWorker(&lock);
      return;
    }
  }

  // We signal a worker. That worker will wake up other workers if needed.
  SignalWork();
}

bool WorkerPool::ShouldCreateWorker() {
  // The task will create a new worker only with the following criteria:
  return !shutting_down_ &&                 // 1. The loop is not shutting down.
         workers_.size() < max_workers_ &&  // 2. We can create more workers.
         !creating_worker_ &&               // 3. A worker is not being created.
         waiting_workers_ == 0 &&           // 4. There are no idle workers.
         !tasks_.empty();                   // 5. There is actual work to do.
}

void WorkerPool::CreateWorker(std::unique_lock<std::mutex>* lock) {
  // NOTE: |lock| is held.
  FX_DCHECK(lock);
  FX_DCHECK(!creating_worker_);
  creating_worker_ = true;
  DEBUG_LOG(WorkerPool) << Preamble() << " Creating a worker.";

  // We can create the worker outside the lock.
  std::unique_ptr<Worker> worker;
  {
    UnlockGuard unlock_guard(*lock);
    worker = std::make_unique<Worker>(this);
    if (observer_)
      observer_->OnWorkerCreation();
    worker->Run();
  }

  // NOTE: |lock| is taken here.
  workers_.push_back(std::move(worker));
}

void WorkerPool::ThreadLoop() {
  DEBUG_LOG(WorkerPool) << Preamble() << " Starting as new thread.";
  std::unique_lock<std::mutex> lock(mutex_);

  // Only one thread must be created at the same time.
  FX_DCHECK(creating_worker_) << " on thread " << std::this_thread::get_id();
  creating_worker_ = false;

  // Only the shutdown thread should be waiting on this CV.
  worker_created_cv_.notify_one();

  while (true) {
    // If we're shutting down. We're out.
    if (shutting_down_)
      break;

    // If there are no new tasks. We simply wait for work.
    if (tasks_.empty()) {
      waiting_workers_++;
      work_available_cv_.wait(lock, [this]() {
        // If we're shutting down, we get out of this CV.
        // Otherwise, we see if there are pending tasks.
        if (shutting_down_)
          return true;
        return !tasks_.empty();
      });
      waiting_workers_--;
    }

    // If we we're woken and we are shutting down, we need to go out.
    if (shutting_down_)
      break;

    // We obtain the task.
    auto task = std::move(tasks_.front());
    tasks_.pop_front();

    // See if we need another worker.
    FX_DCHECK(lock.owns_lock());
    if (ShouldCreateWorker())
      CreateWorker(&lock);

    {
      UnlockGuard unlock_guard(lock);

      // There may be more work available, so we wake up another thread.
      // This is a just in case call.
      SignalWork();

      // Finally we do the task outside the lock.
      task();
      if (observer_)
        observer_->OnExecutingTask();
    }
  }

  DEBUG_LOG(WorkerPool) << Preamble() << " Exiting.";
  if (observer_)
    observer_->OnWorkerExiting();
}

void WorkerPool::Shutdown() {
  {
    std::lock_guard<std::mutex> lock(mutex_);
    if (shutting_down_)
      return;
    shutting_down_ = true;
  }

  if (observer_)
    observer_->OnShutdown();

  // We join all the pending workers and go out.
  JoinAllWorkers();
}

void WorkerPool::JoinAllWorkers() {
  {
    // If there is a thread being created, we need it to be safely created
    // before we can join them.
    std::unique_lock<std::mutex> lock(mutex_);
    FX_DCHECK(shutting_down_);

    // We signal any sleeping workers.
    SignalAllWorkers();

    if (creating_worker_) {
      DEBUG_LOG(WorkerPool) << "Waiting for worker creation before exiting.";
      worker_created_cv_.wait(lock, [this]() { return !creating_worker_; });
    }
  }

  // At this point we know all workers are running or have exited, so we can
  // safely join them.
  for (auto& worker : workers_) {
    worker->Join();
  }
}

void WorkerPool::SignalWork() { work_available_cv_.notify_one(); }

void WorkerPool::SignalAllWorkers() { work_available_cv_.notify_all(); }

}  // namespace debug_ipc
