c6d4cf69创建于 2025年7月8日历史提交
/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define KOALA_INTEROP_MODULE InteropNativeModule
#include "common-interop.h"
#include "interop-types.h"
#include "callback-resource.h"
#include <deque>
#include <unordered_map>


static bool needReleaseFront = false;
static std::deque<CallbackEventKind> callbackEventsQueue;
static std::deque<CallbackBuffer> callbackCallSubqueue;
static std::deque<InteropInt32> callbackResourceSubqueue;

void enqueueCallback(const CallbackBuffer* event)
{
    callbackEventsQueue.push_back(Event_CallCallback);
    callbackCallSubqueue.push_back(*event);
}

void holdManagedCallbackResource(InteropInt32 resourceId)
{
    callbackEventsQueue.push_back(Event_HoldManagedResource);
    callbackResourceSubqueue.push_back(resourceId);
}

void releaseManagedCallbackResource(InteropInt32 resourceId)
{
    callbackEventsQueue.push_back(Event_ReleaseManagedResource);
    callbackResourceSubqueue.push_back(resourceId);
}

KInt impl_CheckCallbackEvent(KByte* buffer, KInt size)
{
    KByte* result = (KByte*)buffer;
    if (needReleaseFront) {
        switch (callbackEventsQueue.front()) {
            case Event_CallCallback:
                callbackCallSubqueue.front().resourceHolder.release();
                callbackCallSubqueue.pop_front();
                break;
            case Event_HoldManagedResource:
            case Event_ReleaseManagedResource:
                callbackResourceSubqueue.pop_front();
                break;
            default:
                INTEROP_FATAL("Unknown event kind");
        }
        callbackEventsQueue.pop_front();
        needReleaseFront = false;
    }
    if (callbackEventsQueue.empty()) {
        return 0;
    }
    const CallbackEventKind frontEventKind = callbackEventsQueue.front();
#ifdef __STDC_LIB_EXT1__
    errno_t res = memcpy_s(result, size, &frontEventKind, 4);
    if (res != EOK) {
        return 0;
    }
#else
    memcpy(result, &frontEventKind, 4);
#endif

    switch (frontEventKind) {
        case Event_CallCallback:
#ifdef __STDC_LIB_EXT1__
            errno_t res = memcpy_s(result + 4, size, callbackCallSubqueue.front().buffer,
                sizeof(CallbackBuffer::buffer));
            if (res != EOK) {
                return 0;
            }
#else
            memcpy(result + 4, callbackCallSubqueue.front().buffer, sizeof(CallbackBuffer::buffer));
#endif
            break;
        case Event_HoldManagedResource:
        case Event_ReleaseManagedResource: {
            const InteropInt32 resourceId = callbackResourceSubqueue.front();
#ifdef __STDC_LIB_EXT1__
            errno_t res = memcpy_s(result + 4, size, &frontEventKind, 4);
            if (res != EOK) {
                return 0;
            }
#else
            memcpy(result + 4, &resourceId, 4);
#endif
            break;
        }
        default:
            INTEROP_FATAL("Unknown event kind");
    }
    needReleaseFront = true;
    return 1;
}
KOALA_INTEROP_2(CheckCallbackEvent, KInt, KByte*, KInt)

void impl_ReleaseCallbackResource(InteropInt32 resourceId)
{
    releaseManagedCallbackResource(resourceId);
}
KOALA_INTEROP_V1(ReleaseCallbackResource, KInt)

void impl_HoldCallbackResource(InteropInt32 resourceId)
{
    holdManagedCallbackResource(resourceId);
}
KOALA_INTEROP_V1(HoldCallbackResource, KInt)