1 /*
2 * Copyright (c) 2021 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 "eventcenter/event_center.h"
17 namespace OHOS {
18 namespace DistributedData {
19 thread_local EventCenter::AsyncQueue *EventCenter::asyncQueue_ = nullptr;
20 constexpr int32_t EventCenter::AsyncQueue::MAX_CAPABILITY;
GetInstance()21 EventCenter &EventCenter::GetInstance()
22 {
23 static EventCenter eventCenter;
24 return eventCenter;
25 }
26
Subscribe(int32_t evtId,const std::function<void (const Event &)> & observer)27 bool EventCenter::Subscribe(int32_t evtId, const std::function<void(const Event &)> &observer)
28 {
29 return observers_.Compute(evtId, [&observer](const auto &id, auto &list) -> bool {
30 list.push_back(observer);
31 return true;
32 });
33 }
34
Unsubscribe(int32_t evtId)35 bool EventCenter::Unsubscribe(int32_t evtId)
36 {
37 return observers_.Erase(evtId);
38 }
39
PostEvent(std::unique_ptr<Event> evt) const40 int32_t EventCenter::PostEvent(std::unique_ptr<Event> evt) const
41 {
42 if (evt == nullptr) {
43 return CODE_INVALID_ARGS;
44 }
45 if (asyncQueue_ == nullptr) {
46 Defer defer;
47 Dispatch(*evt);
48 return CODE_SYNC;
49 }
50 asyncQueue_->Post(std::move(evt));
51 return CODE_ASYNC;
52 }
53
Dispatch(const Event & evt) const54 void EventCenter::Dispatch(const Event &evt) const
55 {
56 auto observers = observers_.Find(evt.GetEventId());
57 if (!observers.first) {
58 return;
59 }
60
61 for (const auto &observer : observers.second) {
62 observer(evt);
63 }
64 }
65
Defer(std::function<void (const Event &)> handler,int32_t evtId)66 EventCenter::Defer::Defer(std::function<void(const Event &)> handler, int32_t evtId)
67 {
68 if (asyncQueue_ == nullptr) {
69 asyncQueue_ = new (std::nothrow) AsyncQueue();
70 }
71
72 if (asyncQueue_ == nullptr) {
73 return;
74 }
75
76 ++(*asyncQueue_);
77 asyncQueue_->AddHandler(evtId, std::move(handler));
78 }
79
~Defer()80 EventCenter::Defer::~Defer()
81 {
82 if (asyncQueue_ == nullptr) {
83 return;
84 }
85 --(*asyncQueue_);
86 if ((*asyncQueue_) <= 0) {
87 delete asyncQueue_;
88 asyncQueue_ = nullptr;
89 }
90 }
91
operator ++()92 EventCenter::AsyncQueue &EventCenter::AsyncQueue::operator++()
93 {
94 ++depth_;
95 return *this;
96 }
97
operator --()98 EventCenter::AsyncQueue &EventCenter::AsyncQueue::operator--()
99 {
100 --depth_;
101 if (depth_ > 0) {
102 return *this;
103 }
104 depth_ = 1;
105 for (int32_t count = 0; !events_.empty() && count < MAX_CAPABILITY; count++) {
106 auto &evt = events_.front();
107 // dispatch to resident handlers
108 GetInstance().Dispatch(*evt);
109
110 // dispatch to temporary handlers
111 auto handler = handlers_.find(evt->GetEventId());
112 if (handler != handlers_.end()) {
113 handler->second(*evt);
114 }
115 events_.pop_front();
116 }
117 depth_ = 0;
118 return *this;
119 }
120
operator <=(int32_t depth) const121 bool EventCenter::AsyncQueue::operator<=(int32_t depth) const
122 {
123 return depth_ <= depth;
124 }
125
Post(std::unique_ptr<Event> evt)126 void EventCenter::AsyncQueue::Post(std::unique_ptr<Event> evt)
127 {
128 for (auto &event : events_) {
129 if (event->GetEventId() != evt->GetEventId()) {
130 continue;
131 }
132
133 if (event->Equals(*evt)) {
134 return;
135 }
136 }
137 events_.push_back(std::move(evt));
138 }
139
AddHandler(int32_t evtId,std::function<void (const Event &)> handler)140 void EventCenter::AsyncQueue::AddHandler(int32_t evtId, std::function<void(const Event &)> handler)
141 {
142 if (evtId == Event::EVT_INVALID || handler == nullptr) {
143 return;
144 }
145
146 // The topper layer event will be effective
147 if (handlers_.find(evtId) != handlers_.end()) {
148 return;
149 }
150
151 handlers_[evtId] = std::move(handler);
152 }
153 } // namespace DistributedData
154 } // namespace OHOS