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