// 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 "src/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
