// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/AsyncTask.h"

#include <utility>

#include "dawn/platform/DawnPlatform.h"

namespace dawn::native {

AsyncTask::State::State(AsyncTaskFunction task) : task(task) {
    DAWN_ASSERT(task);
}

AsyncTask::AsyncTask(AsyncTaskManager* taskManager, AsyncTaskFunction task)
    : mTaskManager(taskManager), mState(task) {
    DAWN_ASSERT(mTaskManager);
}

bool AsyncTask::IsCompleted() const {
    return mState.Use([](auto state) { return state->state != AsyncTaskState::Pending; });
}

void AsyncTask::Wait() {
    mState.Use<NotifyType::None>([](auto state) {
        state.Wait([](auto& x) { return x.state == AsyncTaskState::CompletedCallbacks; });
    });
}

void AsyncTask::AddCompletionCallback(AsyncTaskCompletionCallback completionCallback) {
    bool completeCallbackNow = false;
    mState.Use<NotifyType::None>([&](auto state) {
        if (state->state != AsyncTaskState::Pending) {
            completeCallbackNow = true;
            return;
        }
        state->completionCallbacks.push_back(completionCallback);
    });

    // Call callbacks without holding the lock if the task was already complete.
    if (completeCallbackNow) {
        completionCallback();
    }
}

void AsyncTask::Run() {
    // To ensure we only run the task once, we synchronize it with the lock, move it out when it
    // exists, and call it without holding the lock.
    AsyncTaskFunction task = nullptr;
    mState.Use<NotifyType::None>([&task](auto state) {
        task = std::move(state->task);
        state->task = nullptr;
    });
    DAWN_ASSERT(task);

    // Complete the task and update the state of the task manager. Note we need to make sure we
    // update the state of the task manager before setting the task to Complete to ensure that at
    // teardown when the task manager is waiting on the tasks, that the tasks no longer have a
    // reference to the manager anymore.
    task();
    mTaskManager.ExtractAsDangling()->mTasks.Use([this](auto tasks) { tasks->erase(this); });

    // Update the state and grab the completion callbacks to call them outside the lock scope. Note
    // that we don't notify other threads yet since the callbacks haven't completed.
    std::vector<AsyncTaskCompletionCallback> completionCallbacks;
    mState.Use<NotifyType::None>([&completionCallbacks](auto state) {
        state->state = AsyncTaskState::CompletedTask;

        completionCallbacks = std::move(state->completionCallbacks);
        state->completionCallbacks.clear();
    });
    for (auto completionCallback : completionCallbacks) {
        completionCallback();
    }

    // Finally notify waiting threads.
    mState.Use<NotifyType::All>(
        [](auto state) { state->state = AsyncTaskState::CompletedCallbacks; });
}

ErrorGeneratingAsyncTask::ErrorGeneratingAsyncTask(AsyncTaskManager* taskManager,
                                                   std::function<MaybeError()> task)
    : AsyncTask(taskManager, [this, task] {
          // Wrap the task which returns a MaybeError in a void function and store the error in a
          // member.
          MaybeError taskResult = task();
          if (taskResult.IsError()) {
              mErrorData = taskResult.AcquireError();
          }
      }) {}

bool ErrorGeneratingAsyncTask::IsSuccess() const {
    DAWN_ASSERT(IsCompleted());
    return mErrorData == nullptr;
}

bool ErrorGeneratingAsyncTask::IsError() const {
    DAWN_ASSERT(IsCompleted());
    return mErrorData != nullptr;
}

InternalErrorType ErrorGeneratingAsyncTask::GetErrorType() const {
    return mErrorData ? mErrorData->GetType() : InternalErrorType::None;
}

std::unique_ptr<ErrorData> ErrorGeneratingAsyncTask::AcquireError() {
    DAWN_ASSERT(IsCompleted());
    return std::move(mErrorData);
}

AsyncTaskManager::AsyncTaskManager(dawn::platform::WorkerTaskPool* workerTaskPool)
    : mWorkerTaskPool(workerTaskPool) {}

AsyncTaskManager::~AsyncTaskManager() {
    // Pending tasks call back into this task manager. Make sure they all finish before destructing.
    WaitAllPendingTasks();
}

void AsyncTaskManager::PostConstructedTask(Ref<AsyncTask> asyncTask) {
    // Insert the new task and send it off to the workpool to have it completed.
    mTasks.Use([&asyncTask](auto tasks) { tasks->emplace(asyncTask); });
    mWorkerTaskPool->PostWorkerTask(RunTask, asyncTask.Get());
}

void AsyncTaskManager::WaitAllPendingTasks() {
    TaskSet allTasks;
    mTasks.Use([&allTasks](auto tasks) { allTasks.swap(*tasks); });

    for (auto& task : allTasks) {
        task->Wait();
    }
}

bool AsyncTaskManager::HasPendingTasks() const {
    return mTasks.Use([](auto tasks) { return !tasks->empty(); });
}

void AsyncTaskManager::RunTask(void* task) {
    // Note that we create a new Ref<AsyncTask> here because upon completion, we erase the Ref that
    // the AsyncTaskManager holds which may result in dropping the last reference before the
    // completion of this function otherwise. By explicitly creating a Ref here, we ensure that the
    // last reference is only dropped after the scope of this function.
    Ref<AsyncTask> asyncTask = static_cast<AsyncTask*>(task);
    asyncTask->Run();
}

}  // namespace dawn::native
