Add first version
[ric-plt/sdl.git] / src / engineimpl.cpp
diff --git a/src/engineimpl.cpp b/src/engineimpl.cpp
new file mode 100644 (file)
index 0000000..07bbe53
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   Copyright (c) 2018-2019 Nokia.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+#include "private/engineimpl.hpp"
+#include "private/abort.hpp"
+#include "private/timerfd.hpp"
+#include "private/eventfd.hpp"
+#include "private/system.hpp"
+
+using namespace shareddatalayer;
+
+EngineImpl::EngineImpl():
+    EngineImpl(System::getSystem())
+{
+}
+
+EngineImpl::EngineImpl(System& system):
+    system(system),
+    stopped(false),
+    epollFD(system, system.epoll_create1(EPOLL_CLOEXEC))
+{
+}
+
+EngineImpl::~EngineImpl()
+{
+}
+
+void EngineImpl::handleEvents()
+{
+    if (!handlers.empty())
+        epollWait(0);
+}
+
+void EngineImpl::epollWait(int timeout)
+{
+    ebuffer.resize(handlers.size());
+    const int count(system.epoll_wait(epollFD, ebuffer.data(), static_cast<int>(ebuffer.size()), timeout));
+    if (count <= 0)
+        return;
+    ebuffer.resize(count);
+    for (const auto& i : ebuffer)
+        if (i.data.fd != -1)
+            callHandler(i);
+}
+
+void EngineImpl::callHandler(const epoll_event& e)
+{
+    handlers[e.data.fd](e.events);
+}
+
+void EngineImpl::addMonitoredFD(int fd, unsigned int events, const EventHandler& eh)
+{
+    if (handlers.find(fd) != handlers.end())
+        SHAREDDATALAYER_ABORT("Monitored fd has already been added");
+
+    epoll_event e = { };
+    e.events = events;
+    e.data.fd = fd;
+    system.epoll_ctl(epollFD, EPOLL_CTL_ADD, fd, &e);
+    handlers.insert(std::make_pair(fd, eh));
+}
+
+void EngineImpl::addMonitoredFD(FileDescriptor& fd, unsigned int events, const EventHandler& eh)
+{
+    int native(fd);
+    addMonitoredFD(native, events, eh);
+
+    fd.atClose([this] (int fd)
+        {
+             deleteMonitoredFD(fd);
+        });
+}
+
+void EngineImpl::modifyMonitoredFD(int fd, unsigned int events)
+{
+    if (handlers.find(fd) == handlers.end())
+        SHAREDDATALAYER_ABORT("Modified monitored fd does not exist");
+
+    epoll_event e = { };
+    e.events = events;
+    e.data.fd = fd;
+    system.epoll_ctl(epollFD, EPOLL_CTL_MOD, fd, &e);
+}
+
+void EngineImpl::deleteMonitoredFD(int fd)
+{
+    const auto i(handlers.find(fd));
+    if (i == handlers.end())
+        SHAREDDATALAYER_ABORT("Monitored (to be deleted) fd does not exist");
+
+    handlers.erase(i);
+    for (auto& i : ebuffer)
+        if (i.data.fd == fd)
+        {
+            i.data.fd = -1;
+            break;
+        }
+    system.epoll_ctl(epollFD, EPOLL_CTL_DEL, fd, nullptr);
+}
+
+void EngineImpl::armTimer(Timer& timer, const Timer::Duration& duration, const Timer::Callback& cb)
+{
+    getTimerFD().arm(timer, duration, cb);
+}
+
+void EngineImpl::disarmTimer(const Timer& timer)
+{
+    getTimerFD().disarm(timer);
+}
+
+void EngineImpl::postCallback(const Callback& callback)
+{
+    getEventFD().post(callback);
+}
+
+void EngineImpl::run()
+{
+    while (!stopped)
+        epollWait(-1);
+    stopped = false;
+}
+
+void EngineImpl::stop()
+{
+    postCallback([this] () { stopped = true; });
+}
+
+TimerFD& EngineImpl::getTimerFD()
+{
+    if (!timerFD)
+        timerFD.reset(new TimerFD(system, *this));
+
+    return *timerFD;
+}
+
+EventFD& EngineImpl::getEventFD()
+{
+    if (!eventFD)
+        eventFD.reset(new EventFD(system, *this));
+
+    return *eventFD;
+}