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