• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include <algorithm>
17 #include <cstdint>
18 #include <mutex>
19 #include <string>
20 #include "condition_variable.h"
21 #include "helper/napi_helper.h"
22 
23 namespace Commonlibrary::Concurrent::Condition {
24 
25 std::unordered_map<std::string, ConditionVariable *> ConditionVariable::condMap_;
26 std::mutex ConditionVariable::mapMtx_;
27 
ConditionVariable()28 ConditionVariable::ConditionVariable()
29 {
30     IncreaseRefCount();
31 }
32 
ConditionVariable(const std::string & name)33 ConditionVariable::ConditionVariable(const std::string &name) : name_(name)
34 {
35     IncreaseRefCount();
36 }
37 
FindOrCreateCondition(const std::string & name)38 ConditionVariable *ConditionVariable::FindOrCreateCondition(const std::string &name)
39 {
40     std::lock_guard<std::mutex> mapLock(mapMtx_);
41     ConditionVariable *cond {nullptr};
42     if (condMap_.find(name) == condMap_.end()) {
43         cond = new ConditionVariable(name);
44         condMap_.emplace(name, cond);
45     } else {
46         cond = condMap_[name];
47         cond->IncreaseRefCount();
48     }
49     return cond;
50 }
51 
TryRemoveCondition()52 void ConditionVariable::TryRemoveCondition()
53 {
54     {
55         std::lock_guard<std::mutex> lock(mtx_);
56         --refCount_;
57         if (refCount_ != 0) {
58             return;
59         }
60         if (name_.empty()) {
61             delete this;
62             return;
63         }
64     }
65     std::lock_guard<std::mutex> mapLock(mapMtx_);
66     std::lock_guard<std::mutex> lock(mtx_);
67     if (refCount_ != 0 || condMap_.find(name_) == condMap_.end()) {
68         return;
69     }
70     condMap_.erase(name_);
71     delete this;
72 }
73 
AddTask(napi_env env,napi_deferred deferred,uint64_t timeout)74 void ConditionVariable::AddTask(napi_env env, napi_deferred deferred, uint64_t timeout)
75 {
76     ConditionTask *task = new ConditionTask(this, env, deferred, timeout);
77     std::lock_guard<std::mutex> lock(mtx_);
78     tasks_.emplace_back(task);
79     ++refCount_;
80 }
81 
FinishTask(bool finishAll)82 void ConditionVariable::FinishTask(bool finishAll)
83 {
84     std::lock_guard<std::mutex> lock(mtx_);
85     while (!tasks_.empty()) {
86         ConditionTask *task = tasks_.front();
87         tasks_.pop_front();
88         napi_send_event(
89             task->GetEnv(),
90             [cond = this, task]() {
91                 task->Finish(ConditionTaskFinishReason::NOTIFY);
92                 cond->TryRemoveCondition();
93             },
94             napi_eprio_immediate);
95         if (!finishAll) {
96             break;
97         }
98     }
99 }
100 
FindAndFinishTask(ConditionTask * task,ConditionTaskFinishReason reason)101 void ConditionVariable::FindAndFinishTask(ConditionTask *task, ConditionTaskFinishReason reason)
102 {
103     {
104         std::lock_guard<std::mutex> lock(mtx_);
105         auto it = std::find(tasks_.begin(), tasks_.end(), task);
106         if (it == tasks_.end()) {
107             return;
108         }
109         tasks_.erase(it);
110     }
111     task->Finish(reason);
112     TryRemoveCondition();
113 }
114 
GetRefCount()115 uint32_t ConditionVariable::GetRefCount()
116 {
117     std::lock_guard<std::mutex> lock(mtx_);
118     return refCount_;
119 }
120 
IncreaseRefCount()121 void ConditionVariable::IncreaseRefCount()
122 {
123     std::lock_guard<std::mutex> lock(mtx_);
124     ++refCount_;
125 }
126 
DecreaseRefCount()127 void ConditionVariable::DecreaseRefCount()
128 {
129     std::lock_guard<std::mutex> lock(mtx_);
130     --refCount_;
131 }
132 
133 }  // namespace Commonlibrary::Concurrent::Condition
134