• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ark_native_timer.h"
17 
18 #include "securec.h"
19 
20 #include "utils/log.h"
21 
TimerCallback(uv_timer_t * timerReq)22 void NativeTimerCallbackInfo::TimerCallback(uv_timer_t* timerReq)
23 {
24     NativeTimerCallbackInfo* info = reinterpret_cast<NativeTimerCallbackInfo*>(timerReq->data);
25     bool repeat = info->repeat_;
26     if (!repeat) {
27         info->timeoutExecuting_ = true;
28     }
29     info->cb_(info->data_);
30     if (!repeat) {
31         info->Erase();
32         delete info;
33         info = nullptr;
34     }
35 }
36 
TimerTaskCallback(EcmaVM * vm,void * data,TimerCallbackFunc func,uint64_t timeout,bool repeat)37 void *NativeTimerCallbackInfo::TimerTaskCallback(EcmaVM* vm, void* data, TimerCallbackFunc func,
38                                                  uint64_t timeout, bool repeat)
39 {
40     if (vm == nullptr || func == nullptr) {
41         HILOG_ERROR("TimerTaskCallback input is nullptr");
42         return nullptr;
43     }
44     ArkNativeEngine* engine = reinterpret_cast<ArkNativeEngine*>(JSNApi::GetEnv(vm));
45     NativeTimerCallbackInfo* info = new NativeTimerCallbackInfo(engine, func, data, repeat);
46     if (!info->Init(timeout)) {
47         HILOG_ERROR("NativeTimerCallbackInfo init failed");
48         delete info;
49         info = nullptr;
50         return nullptr;
51     }
52     info->Insert();
53     if (JSNApi::IsJSMainThreadOfEcmaVM(vm)) {
54         uv_loop_t* loop = reinterpret_cast<uv_loop_t*>(engine->GetUVLoop());
55         // main thread need send signal to trigger timer
56         uv_async_send(&loop->wq_async);
57     }
58     return reinterpret_cast<void*>(info);
59 }
60 
CancelTimerCallback(void * timerCallbackInfo)61 void NativeTimerCallbackInfo::CancelTimerCallback(void* timerCallbackInfo)
62 {
63     if (timerCallbackInfo == nullptr) {
64         HILOG_ERROR("CancelTimerCallback info is nullptr");
65         return;
66     }
67     NativeTimerCallbackInfo* info = reinterpret_cast<NativeTimerCallbackInfo*>(timerCallbackInfo);
68     // Timeout will auto delete after executed, if timerCallback contains cancle task will be invalid.
69     // Timeout can be canceled by user only before executing.
70     if (info->timeoutExecuting_) {
71         return;
72     }
73     info->Erase();
74     delete info;
75     info = nullptr;
76 }
77 
Insert()78 void NativeTimerCallbackInfo::Insert()
79 {
80     NativeTimerCallbackInfo* timerListHead = engine_->GetTimerListHead();
81     if (timerListHead) {
82         timerListHead->prev_ = this;
83         next_ = timerListHead;
84     }
85     timerListHead = this;
86     engine_->SetTimerListHead(timerListHead);
87 }
88 
Erase()89 void NativeTimerCallbackInfo::Erase()
90 {
91     if (prev_) {
92         prev_->next_ = next_;
93     }
94     if (this == engine_->GetTimerListHead()) {
95         engine_->SetTimerListHead(next_);
96     }
97     if (next_) {
98         next_->prev_ = prev_;
99     }
100     next_ = nullptr;
101     prev_ = nullptr;
102 }
103 
ReleaseTimerList(ArkNativeEngine * engine)104 void NativeTimerCallbackInfo::ReleaseTimerList(ArkNativeEngine* engine)
105 {
106     for (NativeTimerCallbackInfo* info = engine->GetTimerListHead();
107         info != nullptr; info = engine->GetTimerListHead()) {
108         info->Erase();
109         delete info;
110         info = nullptr;
111     }
112 }
113 
Init(uint64_t timeout)114 bool NativeTimerCallbackInfo::Init(uint64_t timeout)
115 {
116     if (!engine_) {
117         HILOG_ERROR("NativeTimerCallbackInfo engine_ is nullptr");
118         return false;
119     }
120     uv_loop_t* loop = reinterpret_cast<uv_loop_t*>(engine_->GetUVLoop());
121     if (!loop) {
122         HILOG_ERROR("NativeTimerCallbackInfo loop is nullptr");
123         return false;
124     }
125     timerReq_ = new uv_timer_t();
126     if (!timerReq_) {
127         HILOG_ERROR("NativeTimerCallbackInfo timerReq_ is nullptr");
128         return false;
129     }
130     timerReq_->data = this;
131     if (uv_timer_init(loop, timerReq_) != EOK) {
132         HILOG_ERROR("NativeTimerCallbackInfo uv_timer_init failed");
133         delete timerReq_;
134         timerReq_ = nullptr;
135         return false;
136     }
137     if (uv_timer_start(timerReq_, TimerCallback, timeout, timeout) != EOK) {
138         HILOG_ERROR("NativeTimerCallbackInfo uv_timer_start failed");
139         uv_close(reinterpret_cast<uv_handle_t*>(timerReq_), nullptr);
140         delete timerReq_;
141         timerReq_ = nullptr;
142         return false;
143     }
144     return true;
145 }