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