• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 OHOS_FFI_FFI_REMOTE_DATA_H
17 #define OHOS_FFI_FFI_REMOTE_DATA_H
18 
19 #include "nocopyable.h"
20 #include "refbase.h"
21 #include "unordered_map"
22 
23 #include <mutex>
24 
25 #include "cj_fn_invoker.h"
26 #include "runtimetype.h"
27 
28 namespace OHOS::FFI {
29 
30 constexpr int64_t MAX_INT64 = 0x7fffffffffffffff;
31 
32 class RemoteData;
33 class FFIData;
34 
35 class FFI_EXPORT FFIDataManager {
36 public:
37     static FFIDataManager* GetInstance();
38 
39     DISALLOW_COPY_AND_MOVE(FFIDataManager);
40     FFIDataManager() = default;
41 
GetFFIData(int64_t id)42     sptr<FFIData> GetFFIData(int64_t id)
43     {
44         std::lock_guard<std::recursive_mutex> lock(mtx);
45         auto itor = ffiDataStore_.find(id);
46         if (itor == ffiDataStore_.end()) {
47             return nullptr;
48         }
49         return itor->second;
50     }
51 
GetRemoteData(int64_t id)52     sptr<RemoteData> GetRemoteData(int64_t id)
53     {
54         std::lock_guard<std::recursive_mutex> lock(mtx);
55         auto itor = remoteDataStore_.find(id);
56         if (itor == remoteDataStore_.end()) {
57             return nullptr;
58         }
59         return itor->second.promote();
60     }
61     void StoreFFIData(const sptr<FFIData>& data);
62     void StoreRemoteData(const sptr<RemoteData>& data);
RemoveFFIData(int64_t id)63     void RemoveFFIData(int64_t id)
64     {
65         std::lock_guard<std::recursive_mutex> lock(mtx);
66         ffiDataStore_.erase(id);
67     }
RemoveRemoteData(int64_t id)68     void RemoveRemoteData(int64_t id)
69     {
70         std::lock_guard<std::recursive_mutex> lock(mtx);
71         remoteDataStore_.erase(id);
72     }
73 
74     int64_t NewFFIDataId();
75 
76 private:
77     friend class FFIData;
78     uint64_t curFFIDataId_ = 0;
79     const int64_t maxId = MAX_INT64;
80     // maxCapacity can be set to a larger number if needed, make sure maxCapacity is not larger than maxId
81     const int64_t maxCapacity = MAX_INT64;
82     std::recursive_mutex mtx;
83 
84     std::unordered_map<int64_t, sptr<FFIData>> ffiDataStore_;
85     std::unordered_map<int64_t, wptr<RemoteData>> remoteDataStore_;
86 
FFIDataExist(int64_t id)87     bool FFIDataExist(int64_t id) const
88     {
89         return ffiDataStore_.find(id) != ffiDataStore_.end();
90     }
91 
92     int FFIDataIdSafeIncrease();
93 };
94 
95 #define CJ_REMOTE_CLASS(className)                               \
96     DECL_TYPE(className, RemoteData)                           \
97 public:                                                        \
98     friend class RefBase;                                      \
99     friend class RemoteData;                                   \
100     DISALLOW_COPY_AND_MOVE(className);                         \
101     className() = delete;                                      \
102                                                                \
103 protected:                                                     \
104     explicit className(int64_t id) : OHOS::FFI::RemoteData(id) \
105     {}
106 
107 /**
108  * a reference of cj FFIData object.
109  *  standard create procedure:
110  *      1. cj: create FFIData
111  *      2. cj: register to FFIDataManager
112  *      3. cj: pass id to native
113  *      4. native: RemoteData::Create
114  *  standard destroy procedure:
115  *      1. native: ~RemoteData
116  *      2. cj: remove from FFIDataManager
117  *      3. cj: FFIData::onDestroyed
118  */
119 class FFI_EXPORT RemoteData : public TypeBase, public virtual RefBase {
120     DECL_TYPE(RemoteData, TypeBase)
121 public:
122     DISALLOW_COPY_AND_MOVE(RemoteData);
123 
124     template<class T>
Create(int64_t id)125     static sptr<T> Create(int64_t id)
126     {
127         auto manager = FFIDataManager::GetInstance();
128         auto existed = manager->GetRemoteData(id);
129         if (existed != nullptr) {
130             return sptr<T>(existed.GetRefPtr()->template DynamicCast<T>());
131         }
132         auto rawRef = new (std::nothrow) T(id);
133         if (!rawRef) {
134             return nullptr;
135         }
136         sptr<T> ref(rawRef);
137         manager->StoreRemoteData(ref);
138 
139         return ref;
140     }
141 
142     ~RemoteData() override;
143 
144 protected:
145     explicit RemoteData(int64_t id);
146 
147 private:
148     friend class RefBase;
149 
150 public:
151     int64_t GetID() const;
152 
153 private:
154     int64_t id_;
155     bool isValid_;
156 };
157 
158 class FFI_EXPORT CJLambdaRemoteData : public RemoteData {
DECL_TYPE(CJLambdaRemoteData,RemoteData)159     DECL_TYPE(CJLambdaRemoteData, RemoteData)
160 public:
161     explicit CJLambdaRemoteData(int64_t id): RemoteData(id) {}
162 
163     ~CJLambdaRemoteData() override;
164 };
165 
166 /**
167  * object to referenced by cj.
168  *  standard create procedure:
169  *      0. native: Define class derived from FFIData with macro DECL_TYPE to support safe dynamic cast
170  *      1. native: FFIData::Create
171  *      2. native: register to FFIDataManager
172  *      3. native: pass to cj side
173  *      4. cj: create RemoteData
174  *      5. cj: register to RemoteDataManager
175  *  standard destroy procedure:
176  *      1. cj: RemoteData.release
177  *      2. native: remove from FFIDataManager
178  *      3. native: ~FFIData
179  *      4. cj: RemoteData.onDestroyed
180  */
181 class FFI_EXPORT FFIData : public TypeBase, public RefBase {
182     DECL_TYPE(FFIData, TypeBase)
183 public:
184     DISALLOW_COPY_AND_MOVE(FFIData);
FFIData()185     FFIData() : id_(FFIDataManager::GetInstance()->NewFFIDataId()) {}
186     ~FFIData() override;
187 
188     template<class T, class... Args>
Create(Args...args)189     static sptr<T> Create(Args... args)
190     {
191         auto rawPtr = new (std::nothrow) T(std::forward<Args>(args)...);
192         if (!rawPtr) {
193             return nullptr;
194         }
195         sptr<T> ref = rawPtr;
196         FFIDataManager::GetInstance()->StoreFFIData(ref);
197         return ref;
198     }
199 
200     template<class T>
GetData(int64_t id)201     static sptr<T> GetData(int64_t id)
202     {
203         auto data = FFIDataManager::GetInstance()->GetFFIData(id);
204         if (data != nullptr) {
205             return sptr<T>(data.GetRefPtr()->template DynamicCast<T>());
206         }
207         return nullptr;
208     }
209 
Release(int64_t id)210     static void Release(int64_t id)
211     {
212         FFIDataManager::GetInstance()->RemoveFFIData(id);
213     }
Exist(int64_t id)214     static bool Exist(int64_t id)
215     {
216         auto& store_ = FFIDataManager::GetInstance()->ffiDataStore_;
217         return store_.find(id) != store_.end();
218     }
219 
GetID()220     int64_t GetID() const
221     {
222         return id_;
223     }
224 
225 private:
226     int64_t id_;
227 };
228 
229 } // namespace OHOS::FFI
230 
231 #endif // OHOS_FFI_FFI_REMOTE_DATA_H
232