--- /dev/null
+/*
+ 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;
+}