• 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 #ifndef CALLBACK_MANAGER_H
17 #define CALLBACK_MANAGER_H
18 
19 #include <mutex>
20 #include "location_napi_errcode.h"
21 namespace OHOS {
22 namespace Location {
23 template <typename T>
24 class CallbackManager {
25 public:
26     CallbackManager() = default;
27     virtual ~CallbackManager() = default;
28     bool IsCallbackInMap(const napi_env& env, const napi_value& handler);
29     void AddCallback(const napi_env& env, const napi_ref& handlerRef, const sptr<T>& callback);
30     void DeleteCallback(const napi_env& env, const napi_value& handler);
31     sptr<T> GetCallbackPtr(const napi_env& env, const napi_value& handler);
32     void DeleteCallbackByEnv(const napi_env& env);
33     std::map<napi_env, std::map<napi_ref, sptr<T>>> GetCallbackMap();
34     bool RegCallback(const napi_env& env, const size_t argc, const napi_value* argv);
35     LocationErrCode SubscribeChange(const napi_env& env, const napi_ref& handlerRef, sptr<T>& callbackHost);
36 private:
37     std::map<napi_env, std::map<napi_ref, sptr<T>>> callbackMap_;
38     std::mutex mutex_;
39 };
40 
41 template <typename T>
GetCallbackMap()42 std::map<napi_env, std::map<napi_ref, sptr<T>>> CallbackManager<T>::GetCallbackMap()
43 {
44     std::unique_lock<std::mutex> lock(mutex_);
45     return callbackMap_;
46 }
47 
48 template <typename T>
DeleteCallbackByEnv(const napi_env & env)49 void CallbackManager<T>::DeleteCallbackByEnv(const napi_env& env)
50 {
51     std::unique_lock<std::mutex> lock(mutex_);
52     auto iter = callbackMap_.find(env);
53     if (iter == callbackMap_.end()) {
54         return;
55     }
56     iter->second.clear();
57     callbackMap_.erase(iter);
58 }
59 
60 template <typename T>
IsCallbackInMap(const napi_env & env,const napi_value & handler)61 bool CallbackManager<T>::IsCallbackInMap(const napi_env& env, const napi_value& handler)
62 {
63     std::unique_lock<std::mutex> lock(mutex_);
64     auto iter = callbackMap_.find(env);
65     if (iter == callbackMap_.end()) {
66         return false;
67     }
68     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
69         auto ref = innerIter->first;
70         if (IsCallbackEquals(env, handler, ref)) {
71             return true;
72         }
73     }
74     return false;
75 }
76 
77 template <typename T>
AddCallback(const napi_env & env,const napi_ref & handlerRef,const sptr<T> & callback)78 void CallbackManager<T>::AddCallback(const napi_env& env, const napi_ref& handlerRef, const sptr<T>& callback)
79 {
80     std::unique_lock<std::mutex> lock(mutex_);
81     auto iter = callbackMap_.find(env);
82     if (iter == callbackMap_.end()) {
83         std::map<napi_ref, sptr<T>> innerMap;
84         innerMap.insert(std::make_pair(handlerRef, callback));
85         callbackMap_.insert(std::make_pair(env, innerMap));
86         return;
87     }
88     iter->second.insert(std::make_pair(handlerRef, callback));
89 }
90 
91 template <typename T>
DeleteCallback(const napi_env & env,const napi_value & handler)92 void CallbackManager<T>::DeleteCallback(const napi_env& env, const napi_value& handler)
93 {
94     std::unique_lock<std::mutex> lock(mutex_);
95     auto iter = callbackMap_.find(env);
96     if (iter == callbackMap_.end()) {
97         return;
98     }
99     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
100         auto ref = innerIter->first;
101         if (IsCallbackEquals(env, handler, ref)) {
102             innerIter = iter->second.erase(innerIter);
103             if (iter->second.size() == 0) {
104                 callbackMap_.erase(iter);
105             }
106             break;
107         }
108     }
109 }
110 
111 template <typename T>
GetCallbackPtr(const napi_env & env,const napi_value & handler)112 sptr<T> CallbackManager<T>::GetCallbackPtr(const napi_env& env, const napi_value& handler)
113 {
114     std::unique_lock<std::mutex> lock(mutex_);
115     auto iter = callbackMap_.find(env);
116     if (iter == callbackMap_.end()) {
117         return nullptr;
118     }
119     for (auto innerIter = iter->second.begin(); innerIter != iter->second.end(); innerIter++) {
120         auto ref = innerIter->first;
121         if (IsCallbackEquals(env, handler, ref)) {
122             return innerIter->second;
123         }
124     }
125     return nullptr;
126 }
127 
128 template<typename T>
RegCallback(const napi_env & env,const size_t argc,const napi_value * argv)129 bool CallbackManager<T>::RegCallback(const napi_env& env, const size_t argc, const napi_value* argv)
130 {
131     if (argc != PARAM2) {
132         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
133         return false;
134     }
135     if (!CheckIfParamIsFunctionType(env, argv[PARAM1])) {
136         HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
137         return false;
138     }
139     if (IsCallbackInMap(env, argv[PARAM1])) {
140         LBSLOGE(LOCATION_NAPI, "%{public}s, This request already exists", __func__);
141         return false;
142     }
143     auto callbackHost = sptr<T>(new (std::nothrow) T());
144     if (callbackHost != nullptr) {
145         napi_ref handlerRef = nullptr;
146         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM1], 1, &handlerRef), false);
147 
148         LocationErrCode errorCode = SubscribeChange(env, handlerRef, callbackHost);
149         if (errorCode != ERRCODE_SUCCESS) {
150             HandleSyncErrCode(env, errorCode);
151             return false;
152         }
153         AddCallback(env, handlerRef, callbackHost);
154     }
155     return true;
156 }
157 
158 template<typename T>
SubscribeChange(const napi_env & env,const napi_ref & handlerRef,sptr<T> & callbackHost)159 LocationErrCode CallbackManager<T>::SubscribeChange(const napi_env& env,
160     const napi_ref& handlerRef, sptr<T>& callbackHost)
161 {
162     callbackHost->SetEnv(env);
163     callbackHost->SetHandleCb(handlerRef);
164     return ERRCODE_SUCCESS;
165 }
166 } // namespace Location
167 } // namespace OHOS
168 #endif // CALLBACK_MANAGER_H
169