RIC:1060: Change in PTL
[ric-plt/sdl.git] / src / engineimpl.cpp
1 /*
2    Copyright (c) 2018-2019 Nokia.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20 */
21
22 #include "private/engineimpl.hpp"
23 #include "private/abort.hpp"
24 #include "private/timerfd.hpp"
25 #include "private/eventfd.hpp"
26 #include "private/system.hpp"
27
28 using namespace shareddatalayer;
29
30 EngineImpl::EngineImpl():
31     EngineImpl(System::getSystem())
32 {
33 }
34
35 EngineImpl::EngineImpl(System& system):
36     system(system),
37     stopped(false),
38     epollFD(system, system.epoll_create1(EPOLL_CLOEXEC))
39 {
40 }
41
42 EngineImpl::~EngineImpl()
43 {
44 }
45
46 void EngineImpl::handleEvents()
47 {
48     if (!handlers.empty())
49         epollWait(0);
50 }
51
52 void EngineImpl::epollWait(int timeout)
53 {
54     ebuffer.resize(handlers.size());
55     const int count(system.epoll_wait(epollFD, ebuffer.data(), static_cast<int>(ebuffer.size()), timeout));
56     if (count <= 0)
57         return;
58     ebuffer.resize(count);
59     for (const auto& i : ebuffer)
60         if (i.data.fd != -1)
61             callHandler(i);
62 }
63
64 void EngineImpl::callHandler(const epoll_event& e)
65 {
66     handlers[e.data.fd](e.events);
67 }
68
69 void EngineImpl::addMonitoredFD(int fd, unsigned int events, const EventHandler& eh)
70 {
71     if (handlers.find(fd) != handlers.end())
72         SHAREDDATALAYER_ABORT("Monitored fd has already been added");
73
74     epoll_event e = { };
75     e.events = events;
76     e.data.fd = fd;
77     system.epoll_ctl(epollFD, EPOLL_CTL_ADD, fd, &e);
78     handlers.insert(std::make_pair(fd, eh));
79 }
80
81 void EngineImpl::addMonitoredFD(FileDescriptor& fd, unsigned int events, const EventHandler& eh)
82 {
83     int native(fd);
84     addMonitoredFD(native, events, eh);
85
86     fd.atClose([this] (int fd)
87         {
88              deleteMonitoredFD(fd);
89         });
90 }
91
92 void EngineImpl::modifyMonitoredFD(int fd, unsigned int events)
93 {
94     if (handlers.find(fd) == handlers.end())
95         SHAREDDATALAYER_ABORT("Modified monitored fd does not exist");
96
97     epoll_event e = { };
98     e.events = events;
99     e.data.fd = fd;
100     system.epoll_ctl(epollFD, EPOLL_CTL_MOD, fd, &e);
101 }
102
103 void EngineImpl::deleteMonitoredFD(int fd)
104 {
105     const auto i(handlers.find(fd));
106     if (i == handlers.end())
107         SHAREDDATALAYER_ABORT("Monitored (to be deleted) fd does not exist");
108
109     handlers.erase(i);
110     for (auto& i : ebuffer)
111         if (i.data.fd == fd)
112         {
113             i.data.fd = -1;
114             break;
115         }
116     system.epoll_ctl(epollFD, EPOLL_CTL_DEL, fd, nullptr);
117 }
118
119 void EngineImpl::armTimer(Timer& timer, const Timer::Duration& duration, const Timer::Callback& cb)
120 {
121     getTimerFD().arm(timer, duration, cb);
122 }
123
124 void EngineImpl::disarmTimer(const Timer& timer)
125 {
126     getTimerFD().disarm(timer);
127 }
128
129 void EngineImpl::postCallback(const Callback& callback)
130 {
131     getEventFD().post(callback);
132 }
133
134 void EngineImpl::run()
135 {
136     while (!stopped)
137         epollWait(-1);
138     stopped = false;
139 }
140
141 void EngineImpl::stop()
142 {
143     postCallback([this] () { stopped = true; });
144 }
145
146 TimerFD& EngineImpl::getTimerFD()
147 {
148     if (!timerFD)
149         timerFD.reset(new TimerFD(system, *this));
150
151     return *timerFD;
152 }
153
154 EventFD& EngineImpl::getEventFD()
155 {
156     if (!eventFD)
157         eventFD.reset(new EventFD(system, *this));
158
159     return *eventFD;
160 }