* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uv_queue.h"
#include "logger.h"
namespace OHOS::ObjectStore {
UvQueue::UvQueue(napi_env env) : env_(env)
{
napi_get_uv_event_loop(env, &loop_);
}
UvQueue::~UvQueue()
{
LOG_DEBUG("no memory leak for queue-callback");
}
void UvQueue::ExecUvWork(UvEntry *entry)
{
if (entry == nullptr) {
LOG_ERROR("entry is nullptr");
return;
}
auto queue = entry->uvQueue_.lock();
if (queue != nullptr) {
std::unique_lock<std::shared_mutex> cacheLock(queue->mutex_);
for (auto &item : queue->args_) {
item.first(queue->env_, item.second);
}
queue->args_.clear();
}
delete entry;
entry = nullptr;
}
bool UvQueue::CallFunction(Process process, void *argv, const char *type)
{
if (process == nullptr || argv == nullptr) {
LOG_ERROR("nullptr");
return false;
}
auto *uvEntry = new (std::nothrow) UvEntry{ weak_from_this() };
if (uvEntry == nullptr) {
LOG_ERROR("no memory for UvEntry");
return false;
}
auto rollbackAddition = [this, process, argv]() {
std::unique_lock<std::shared_mutex> lock(mutex_);
auto it = args_.find(process);
if (it != args_.end() && !it->second.empty()) {
it->second.pop_back();
if (it->second.empty()) {
args_.erase(it);
}
}
};
{
std::unique_lock<std::shared_mutex> cacheLock(mutex_);
auto &processList = args_[process];
processList.push_back(argv);
}
auto task = [uvEntry]() { UvQueue::ExecUvWork(uvEntry); };
std::string taskName = (type == nullptr) ? "data_object.unknown" : std::string("data_object.") + type;
auto ret = napi_send_event(env_, task, napi_eprio_high, taskName.c_str());
if (ret != 0) {
LOG_ERROR("napi_send_event failed, ret: %{public}d.", ret);
rollbackAddition();
delete uvEntry;
return false;
}
return true;
}
}