• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "datashare_uv_queue.h"
17 #include <thread>
18 #include "datashare_log.h"
19 
20 namespace OHOS {
21 namespace DataShare {
22 constexpr int WAIT_TIME = 3;
23 constexpr int SLEEP_TIME = 100;
24 constexpr int TRY_TIMES = 20;
DataShareUvQueue(napi_env env)25 DataShareUvQueue::DataShareUvQueue(napi_env env)
26     : env_(env)
27 {
28     napi_get_uv_event_loop(env, &loop_);
29 }
30 
SyncCall(NapiVoidFunc func,NapiBoolFunc retFunc)31 void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc)
32 {
33     uv_work_t* work = new (std::nothrow) uv_work_t;
34     if (work == nullptr) {
35         return;
36     }
37     work->data = new UvEntry {env_, std::move(func), false, false, {}, {}, std::move(retFunc)};
38     auto status = uv_queue_work(
39         loop_, work, [](uv_work_t* work) {},
40         [](uv_work_t* work, int uvstatus) {
41             if (work == nullptr || work->data == nullptr) {
42                 LOG_ERROR("invalid work or work->data.");
43                 return;
44             }
45             auto *entry = static_cast<UvEntry*>(work->data);
46             std::unique_lock<std::mutex> lock(entry->mutex);
47             if (entry->func) {
48                 entry->func();
49             }
50             entry->done = true;
51             if (entry->purge) {
52                 DataShareUvQueue::Purge(work);
53             } else {
54                 entry->condition.notify_all();
55             }
56         });
57     if (status != napi_ok) {
58         LOG_ERROR("queue work failed");
59         DataShareUvQueue::Purge(work);
60         return;
61     }
62 
63     bool noNeedPurge = false;
64     auto *uvEntry = static_cast<UvEntry*>(work->data);
65     {
66         if (uvEntry == nullptr) {
67             LOG_ERROR("invalid uvEntry.");
68             return;
69         }
70         std::unique_lock<std::mutex> lock(uvEntry->mutex);
71         if (uvEntry->condition.wait_for(lock, std::chrono::seconds(WAIT_TIME), [uvEntry] { return uvEntry->done; })) {
72             LOG_INFO("function ended successfully");
73         }
74         CheckFuncAndExec(uvEntry->retFunc);
75         if (!uvEntry->done && !uv_cancel((uv_req_t*)&work)) {
76             LOG_ERROR("uv_cancel failed.");
77             uvEntry->purge = true;
78             noNeedPurge = true;
79         }
80     }
81 
82     if (!noNeedPurge) {
83         DataShareUvQueue::Purge(work);
84     }
85 }
86 
Purge(uv_work_t * work)87 void DataShareUvQueue::Purge(uv_work_t* work)
88 {
89     if (work == nullptr) {
90         LOG_ERROR("invalid work");
91         return;
92     }
93     if (work->data == nullptr) {
94         LOG_ERROR("invalid work->data");
95         delete work;
96         return;
97     }
98 
99     auto *entry = static_cast<UvEntry*>(work->data);
100 
101     delete entry;
102     entry = nullptr;
103 
104     delete work;
105     work = nullptr;
106 }
107 
CheckFuncAndExec(NapiBoolFunc retFunc)108 void DataShareUvQueue::CheckFuncAndExec(NapiBoolFunc retFunc)
109 {
110     if (retFunc) {
111         int tryTimes = TRY_TIMES;
112         while (retFunc() != true && tryTimes > 0) {
113             std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
114             tryTimes--;
115         }
116     }
117 }
118 } // namespace DataShare
119 } // namespace OHOS