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 JS_CONCURRENT_MODULE_UTILS_LOCKS_LOCK_REQUEST_H
17 #define JS_CONCURRENT_MODULE_UTILS_LOCKS_LOCK_REQUEST_H
18 
19 #include <memory>
20 #include <queue>
21 #include <string>
22 
23 #include "common.h"
24 #include "helper/error_helper.h"
25 #include "helper/napi_helper.h"
26 #include "helper/object_helper.h"
27 
28 namespace Commonlibrary::Concurrent::LocksModule {
29 enum LockMode {
30     LOCK_MODE_UNLOCK,
31     LOCK_MODE_SHARED,
32     LOCK_MODE_EXCLUSIVE,
33     LOCK_MODE_MAX
34 };
35 
36 struct LockOptions {
37     bool isAvailable = false;
38     napi_ref signal = nullptr;
39     uint32_t timeoutMillis = 0;
40 };
41 
42 class AsyncLock;
43 
44 class LockRequest : public std::enable_shared_from_this<LockRequest> {
45 public:
46     LockRequest(AsyncLock* lock, tid_t tid, napi_env env, napi_ref cb, LockMode mode, const LockOptions &options,
47         napi_deferred deferred);
48     ~LockRequest();
49 
GetWeakPtr()50     std::weak_ptr<LockRequest> GetWeakPtr()
51     {
52         return weak_from_this();
53     }
54 
GetTid()55     tid_t GetTid() const
56     {
57         return tid_;
58     }
59 
GetCreationStacktrace()60     std::string GetCreationStacktrace()
61     {
62         return creationStacktrace_;
63     }
64 
GetMode()65     LockMode GetMode() const
66     {
67         return mode_;
68     }
69 
GetOptions()70     const LockOptions &GetOptions() const
71     {
72         return options_;
73     }
74 
GetEnv()75     napi_env GetEnv()
76     {
77         return env_;
78     }
79 
80     void CallCallbackAsync();
81     void CallCallback();
82 
83     void OnQueued(napi_env env, uint32_t timeoutMillis);
84     void OnSatisfied(napi_env env);
85 
86 private:
87     bool AbortIfNeeded();
88     void ArmTimeoutTimer(napi_env env, uint32_t timeoutMillis);
89     void DisarmTimeoutTimer(napi_env env);
90     void HandleRequestTimeout(std::string &&errorMessage);
91     std::string GetLockInfo() const;
92     void CleanTimer();
93     static void AsyncAfterWorkCallback(napi_env env, napi_status status, void *data);
94     static napi_value FinallyCallback(napi_env env, napi_callback_info info);
95     static void TimeoutCallback(uv_timer_t *handle);
96     static void DeallocateTimeoutTimerCallback(uv_handle_t* handle);
97     static void EnvCleanUp(void* arg);
98     static void StopTimer(napi_env env, napi_value jsCallback, void* context, void* data);
99 
100     AsyncLock* lock_;
101     tid_t tid_;
102     std::string creationStacktrace_;
103     napi_env env_;
104     napi_ref callback_;
105     LockMode mode_;
106     LockOptions options_;
107     napi_deferred deferred_;
108     napi_async_work work_;
109     uv_timer_t *timeoutTimer_;
110     bool timeoutActive_;
111     napi_threadsafe_function stopTimerTsfn_{nullptr};
112     std::mutex lockRequestMutex_;
113 };
114 
115 struct RequestTimeoutData {
RequestTimeoutDataRequestTimeoutData116     RequestTimeoutData(AsyncLock* l, LockRequest* r): lock(l), request(r) {}
117     AsyncLock* lock;
118     LockRequest* request;
119 };
120 
121 }  // namespace Commonlibrary::Concurrent::LocksModule
122 #endif  // JS_CONCURRENT_MODULE_UTILS_LOCKS_LOCK_REQUEST_H
123