/* * Copyright (C) 2022 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. */ #ifndef CALLBACK_MANAGER_H #define CALLBACK_MANAGER_H #include #include "location_napi_errcode.h" namespace OHOS { namespace Location { template class CallbackManager { public: CallbackManager() = default; virtual ~CallbackManager() = default; bool IsCallbackInMap(const napi_env& env, const napi_value& handler); void AddCallback(const napi_env& env, const napi_ref& handlerRef, const sptr& callback); void DeleteCallback(const napi_env& env, const napi_value& handler); sptr GetCallbackPtr(const napi_env& env, const napi_value& handler); void DeleteCallbackByEnv(const napi_env& env); std::map>> GetCallbackMap(); bool RegCallback(const napi_env& env, const size_t argc, const napi_value* argv); LocationErrCode SubscribeChange(const napi_env& env, const napi_ref& handlerRef, sptr& callbackHost); private: std::map>> callbackMap_; std::mutex mutex_; }; template std::map>> CallbackManager::GetCallbackMap() { std::unique_lock lock(mutex_); return callbackMap_; } template void CallbackManager::DeleteCallbackByEnv(const napi_env& env) { std::unique_lock lock(mutex_); auto iter = callbackMap_.find(env); if (iter == callbackMap_.end()) { return; } iter->second.clear(); callbackMap_.erase(iter); } template bool CallbackManager::IsCallbackInMap(const napi_env& env, const napi_value& handler) { std::unique_lock lock(mutex_); auto iter = callbackMap_.find(env); if (iter == callbackMap_.end()) { return false; } for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) { auto ref = innerIter->first; if (IsCallbackEquals(env, handler, ref)) { return true; } } return false; } template void CallbackManager::AddCallback(const napi_env& env, const napi_ref& handlerRef, const sptr& callback) { std::unique_lock lock(mutex_); auto iter = callbackMap_.find(env); if (iter == callbackMap_.end()) { std::map> innerMap; innerMap.insert(std::make_pair(handlerRef, callback)); callbackMap_.insert(std::make_pair(env, innerMap)); return; } iter->second.insert(std::make_pair(handlerRef, callback)); } template void CallbackManager::DeleteCallback(const napi_env& env, const napi_value& handler) { std::unique_lock lock(mutex_); auto iter = callbackMap_.find(env); if (iter == callbackMap_.end()) { return; } for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) { auto ref = innerIter->first; if (IsCallbackEquals(env, handler, ref)) { innerIter = iter->second.erase(innerIter); if (iter->second.size() == 0) { callbackMap_.erase(iter); } break; } } } template sptr CallbackManager::GetCallbackPtr(const napi_env& env, const napi_value& handler) { std::unique_lock lock(mutex_); auto iter = callbackMap_.find(env); if (iter == callbackMap_.end()) { return nullptr; } for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) { auto ref = innerIter->first; if (IsCallbackEquals(env, handler, ref)) { return innerIter->second; } } return nullptr; } template bool CallbackManager::RegCallback(const napi_env& env, const size_t argc, const napi_value* argv) { if (argc != PARAM2) { HandleSyncErrCode(env, ERRCODE_INVALID_PARAM); return false; } if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) { HandleSyncErrCode(env, ERRCODE_INVALID_PARAM); return false; } if (IsCallbackInMap(env, argv[PARAM1])) { LBSLOGE(LOCATION_NAPI, "%{public}s, This request already exists", __func__); return false; } auto callbackHost = sptr(new (std::nothrow) T()); if (callbackHost != nullptr) { napi_ref handlerRef = nullptr; NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], 1, &handlerRef), false); LocationErrCode errorCode = SubscribeChange(env, handlerRef, callbackHost); if (errorCode != ERRCODE_SUCCESS) { HandleSyncErrCode(env, errorCode); return false; } AddCallback(env, handlerRef, callbackHost); } return true; } template LocationErrCode CallbackManager::SubscribeChange(const napi_env& env, const napi_ref& handlerRef, sptr& callbackHost) { callbackHost->SetEnv(env); callbackHost->SetHandleCb(handlerRef); return ERRCODE_SUCCESS; } } // namespace Location } // namespace OHOS #endif // CALLBACK_MANAGER_H