//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLEvent.cpp: Implements the cl::Event class.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/CLEvent.h"

#include "libANGLE/CLCommandQueue.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/cl_utils.h"

#include <cstring>

namespace cl
{

angle::Result Event::setUserEventStatus(cl_int executionStatus)
{
    // we need to retain in the case of situations where any waiting thread(s) on clWaitForEvents
    // get signaled here from backend/mImpl call before we completely finish this routine.
    cl::EventPtr implicitRetain(this);

    ANGLE_TRY(mImpl->setUserEventStatus(executionStatus));
    mStatusWasChanged = true;
    return angle::Result::Continue;
}

angle::Result Event::getInfo(EventInfo name,
                             size_t valueSize,
                             void *value,
                             size_t *valueSizeRet) const
{
    cl_int execStatus     = 0;
    cl_uint valUInt       = 0u;
    void *valPointer      = nullptr;
    const void *copyValue = nullptr;
    size_t copySize       = 0u;

    switch (name)
    {
        case EventInfo::CommandQueue:
            valPointer = CommandQueue::CastNative(mCommandQueue.get());
            copyValue  = &valPointer;
            copySize   = sizeof(valPointer);
            break;
        case EventInfo::CommandType:
            copyValue = &mCommandType;
            copySize  = sizeof(mCommandType);
            break;
        case EventInfo::ReferenceCount:
            valUInt   = getRefCount();
            copyValue = &valUInt;
            copySize  = sizeof(valUInt);
            break;
        case EventInfo::CommandExecutionStatus:
        {
            ANGLE_TRY(mImpl->getCommandExecutionStatus(execStatus));
            copyValue = &execStatus;
            copySize  = sizeof(execStatus);
            break;
        }
        case EventInfo::Context:
            valPointer = mContext->getNative();
            copyValue  = &valPointer;
            copySize   = sizeof(valPointer);
            break;
        default:
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
    }

    if (value != nullptr)
    {
        // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
        // as described in the Event Queries table and param_value is not NULL.
        if (valueSize < copySize)
        {
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
        }
        if (copyValue != nullptr)
        {
            std::memcpy(value, copyValue, copySize);
        }
    }
    if (valueSizeRet != nullptr)
    {
        *valueSizeRet = copySize;
    }
    return angle::Result::Continue;
}

angle::Result Event::setCallback(cl_int commandExecCallbackType, EventCB pfnNotify, void *userData)
{
    auto callbacks = mCallbacks.synchronize();

    // Spec mentions that the callback will be called when the execution status of the event is
    // equal to past the status specified by commandExecCallbackType
    cl_int currentStatus;
    ANGLE_TRY(mImpl->getCommandExecutionStatus(currentStatus));
    if (currentStatus <= commandExecCallbackType)
    {
        pfnNotify(this, commandExecCallbackType, userData);
        return angle::Result::Continue;
    }

    // Only when required register a single callback with the back end for each callback type.
    if ((*callbacks)[commandExecCallbackType].empty())
    {
        ANGLE_TRY(mImpl->setCallback(*this, commandExecCallbackType));
        // This event has to be retained until the callback is called.
        retain();
    }
    (*callbacks)[commandExecCallbackType].emplace_back(pfnNotify, userData);
    return angle::Result::Continue;
}

angle::Result Event::getProfilingInfo(ProfilingInfo name,
                                      size_t valueSize,
                                      void *value,
                                      size_t *valueSizeRet)
{
    return mImpl->getProfilingInfo(name, valueSize, value, valueSizeRet);
}

angle::Result Event::initBackend(const rx::CLEventImpl::CreateFunc &createFunc)
{
    if (isUserEvent())
    {
        return mContext->getImpl().createUserEvent(*this, &mImpl);
    }
    else
    {
        // execute the create func lambda that was passed into this method
        mImpl = createFunc(*this);
        if (mImpl == nullptr)
        {
            ANGLE_CL_RETURN_ERROR(CL_OUT_OF_HOST_MEMORY);
        }
    }

    return angle::Result::Continue;
}

Event::~Event() = default;

void Event::callback(cl_int commandStatus)
{
    ASSERT(commandStatus >= 0 && commandStatus < 3);
    const Callbacks callbacks = std::move(mCallbacks->at(commandStatus));
    for (const CallbackData &data : callbacks)
    {
        data.first(this, commandStatus, data.second);
    }
    // This event can be released after the callback was called.
    if (release())
    {
        delete this;
    }
}

EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList)
{
    EventPtrs events;
    events.reserve(numEvents);
    while (numEvents-- != 0u)
    {
        events.emplace_back(&(*eventList++)->cast<Event>());
    }
    return events;
}

Event::Event(Context &context) : mContext(&context), mCommandType(CL_COMMAND_USER), mImpl(nullptr)
{}

Event::Event(CommandQueue &queue, cl_command_type commandType)
    : mContext(&queue.getContext()),
      mCommandQueue(&queue),
      mCommandType(commandType),
      mImpl(nullptr)
{}

}  // namespace cl
