1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common-interop.h"
17 #include "callback-resource.h"
18 #include <deque>
19 #include <unordered_map>
20 #include <algorithm>
21 #include <stdexcept>
22
23 // NOLINTBEGIN
24
25 static bool needReleaseFront = false;
26 static std::deque<CallbackEventKind> callbackEventsQueue;
27 static std::deque<CallbackBuffer> callbackCallSubqueue;
28 static std::deque<InteropInt32> callbackResourceSubqueue;
29
EnqueueCallback(const CallbackBuffer * event)30 void EnqueueCallback(const CallbackBuffer *event)
31 {
32 callbackEventsQueue.push_back(EVENT_CALL_CALLBACK);
33 callbackCallSubqueue.push_back(*event);
34 }
35
HoldManagedCallbackResource(InteropInt32 resourceId)36 void HoldManagedCallbackResource(InteropInt32 resourceId)
37 {
38 callbackEventsQueue.push_back(EVENT_HOLD_MANAGED_RESOURCE);
39 callbackResourceSubqueue.push_back(resourceId);
40 }
41
ReleaseManagedCallbackResource(InteropInt32 resourceId)42 void ReleaseManagedCallbackResource(InteropInt32 resourceId)
43 {
44 callbackEventsQueue.push_back(EVENT_RELEASE_MANAGED_RESOURCE);
45 callbackResourceSubqueue.push_back(resourceId);
46 }
47
impl_CheckCallbackEvent(KByte * result,KInt size)48 KInt impl_CheckCallbackEvent(KByte *result, [[maybe_unused]] KInt size)
49 {
50 if (needReleaseFront) {
51 switch (callbackEventsQueue.front()) {
52 case EVENT_CALL_CALLBACK:
53 callbackCallSubqueue.front().resourceHolder.release();
54 callbackCallSubqueue.pop_front();
55 break;
56 case EVENT_HOLD_MANAGED_RESOURCE:
57 case EVENT_RELEASE_MANAGED_RESOURCE:
58 callbackResourceSubqueue.pop_front();
59 break;
60 default:
61 throw std::runtime_error("Unknown event kind");
62 }
63 callbackEventsQueue.pop_front();
64 needReleaseFront = false;
65 }
66 if (callbackEventsQueue.empty()) {
67 return 0;
68 }
69 const CallbackEventKind frontEventKind = callbackEventsQueue.front();
70 std::copy_n(&frontEventKind, 4U, result);
71 switch (frontEventKind) {
72 case EVENT_CALL_CALLBACK:
73 std::copy_n(callbackCallSubqueue.front().buffer, sizeof(CallbackBuffer::buffer), result + 4U);
74 break;
75 case EVENT_HOLD_MANAGED_RESOURCE:
76 case EVENT_RELEASE_MANAGED_RESOURCE: {
77 const InteropInt32 resourceId = callbackResourceSubqueue.front();
78 std::copy_n(&resourceId, 4U, result + 4U);
79 break;
80 }
81 default:
82 throw std::runtime_error("Unknown event kind");
83 }
84 needReleaseFront = true;
85 return 1;
86 }
TS_INTEROP_2(CheckCallbackEvent,KInt,KByte *,KInt)87 TS_INTEROP_2(CheckCallbackEvent, KInt, KByte *, KInt)
88
89 void impl_ReleaseCallbackResource(InteropInt32 resourceId)
90 {
91 ReleaseManagedCallbackResource(resourceId);
92 }
TS_INTEROP_V1(ReleaseCallbackResource,KInt)93 TS_INTEROP_V1(ReleaseCallbackResource, KInt)
94
95 void impl_HoldCallbackResource(InteropInt32 resourceId)
96 {
97 HoldManagedCallbackResource(resourceId);
98 }
99 TS_INTEROP_V1(HoldCallbackResource, KInt)
100
101 // NOLINTEND
102