From 7396882735e82ef5f034c46286b0499d8f5437e7 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Mon, 9 Mar 2015 13:34:27 +0100 Subject: [PATCH] Epoll refactor [Bug/Feature] N/A [Cause] N/A [Solution] N/A [Verification] Run tests Change-Id: Iabb0557aa42ff09d0a2b3f9c36b451cf5fdad10f --- common/{utils => epoll}/event-poll.cpp | 6 +- common/{utils => epoll}/event-poll.hpp | 14 +-- common/epoll/events.cpp | 71 +++++++++++++++ common/epoll/events.hpp | 41 +++++++++ common/{utils => epoll}/glib-poll-dispatcher.cpp | 25 +++--- common/{utils => epoll}/glib-poll-dispatcher.hpp | 17 ++-- common/{utils => epoll}/thread-poll-dispatcher.cpp | 24 ++--- common/{utils => epoll}/thread-poll-dispatcher.hpp | 20 +++-- .../unit_tests/{utils => epoll}/ut-event-poll.cpp | 100 ++++++--------------- tests/unit_tests/ipc/ut-ipc.cpp | 1 - 10 files changed, 199 insertions(+), 120 deletions(-) rename common/{utils => epoll}/event-poll.cpp (98%) rename common/{utils => epoll}/event-poll.hpp (89%) create mode 100644 common/epoll/events.cpp create mode 100644 common/epoll/events.hpp rename common/{utils => epoll}/glib-poll-dispatcher.cpp (70%) rename common/{utils => epoll}/glib-poll-dispatcher.hpp (80%) rename common/{utils => epoll}/thread-poll-dispatcher.cpp (73%) rename common/{utils => epoll}/thread-poll-dispatcher.hpp (77%) rename tests/unit_tests/{utils => epoll}/ut-event-poll.cpp (58%) diff --git a/common/utils/event-poll.cpp b/common/epoll/event-poll.cpp similarity index 98% rename from common/utils/event-poll.cpp rename to common/epoll/event-poll.cpp index b37d727..dc1c1bc 100644 --- a/common/utils/event-poll.cpp +++ b/common/epoll/event-poll.cpp @@ -23,7 +23,7 @@ */ #include "config.hpp" -#include "utils/event-poll.hpp" +#include "epoll/event-poll.hpp" #include "utils/fd-utils.hpp" #include "utils/exception.hpp" #include "logger/logger.hpp" @@ -34,7 +34,7 @@ #include namespace vasum { -namespace utils { +namespace epoll { EventPoll::EventPoll() : mPollFD(::epoll_create1(EPOLL_CLOEXEC)) @@ -147,5 +147,5 @@ void EventPoll::removeFDInternal(const int fd) } } -} // namespace utils +} // namespace epoll } // namespace vasum diff --git a/common/utils/event-poll.hpp b/common/epoll/event-poll.hpp similarity index 89% rename from common/utils/event-poll.hpp rename to common/epoll/event-poll.hpp index 1a7ae2c..2d37aaa 100644 --- a/common/utils/event-poll.hpp +++ b/common/epoll/event-poll.hpp @@ -22,8 +22,10 @@ * @brief C++ epoll wrapper */ -#ifndef COMMON_UTILS_EVENT_POLL_HPP -#define COMMON_UTILS_EVENT_POLL_HPP +#ifndef COMMON_EPOLL_EVENT_POLL_HPP +#define COMMON_EPOLL_EVENT_POLL_HPP + +#include "epoll/events.hpp" #include #include @@ -31,12 +33,10 @@ #include namespace vasum { -namespace utils { +namespace epoll { class EventPoll { public: - - typedef unsigned int Events; typedef std::function Callback; EventPoll(); @@ -62,7 +62,7 @@ private: }; -} // namespace utils +} // namespace epoll } // namespace vasum -#endif // COMMON_UTILS_EVENT_POLL_HPP +#endif // COMMON_EPOLL_EVENT_POLL_HPP diff --git a/common/epoll/events.cpp b/common/epoll/events.cpp new file mode 100644 index 0000000..1ee27e0 --- /dev/null +++ b/common/epoll/events.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * 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 + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Epoll events + */ + +#include "config.hpp" +#include "epoll/events.hpp" + +#include + +namespace vasum { +namespace epoll { + +namespace { + +std::string eventToString(Events event) +{ + switch (event) { + case EPOLLIN: return "IN"; + case EPOLLOUT: return "OUT"; + case EPOLLERR: return "ERR"; + case EPOLLHUP: return "HUP"; + case EPOLLRDHUP: return "RDHUP"; + default: + std::ostringstream ss; + ss << "0x" << std::hex << event; + return ss.str(); + } +} + +} // namespace + +std::string eventsToString(Events events) +{ + if (events == 0) { + return ""; + } + std::string ret; + for (unsigned int i = 0; i<32; ++i) { + Events event = 1u << i; + if (events & event) { + if (!ret.empty()) { + ret.append(", "); + } + ret.append(eventToString(event)); + } + } + return ret; +} + +} // namespace epoll +} // namespace vasum diff --git a/common/epoll/events.hpp b/common/epoll/events.hpp new file mode 100644 index 0000000..62eb00a --- /dev/null +++ b/common/epoll/events.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * 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 + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Epoll events + */ + +#ifndef COMMON_EPOLL_EVENTS_HPP +#define COMMON_EPOLL_EVENTS_HPP + +#include +#include // for EPOLL* constatnts + +namespace vasum { +namespace epoll { + +typedef unsigned int Events; ///< bitmask of EPOLL* constants + +std::string eventsToString(Events events); + +} // namespace epoll +} // namespace vasum + +#endif // COMMON_EPOLL_EVENTS_HPP diff --git a/common/utils/glib-poll-dispatcher.cpp b/common/epoll/glib-poll-dispatcher.cpp similarity index 70% rename from common/utils/glib-poll-dispatcher.cpp rename to common/epoll/glib-poll-dispatcher.cpp index 5c66d16..cde535d 100644 --- a/common/utils/glib-poll-dispatcher.cpp +++ b/common/epoll/glib-poll-dispatcher.cpp @@ -23,22 +23,22 @@ */ #include "config.hpp" -#include "utils/glib-poll-dispatcher.hpp" +#include "epoll/glib-poll-dispatcher.hpp" #include "utils/callback-wrapper.hpp" namespace vasum { -namespace utils { +namespace epoll { -GlibPollDispatcher::GlibPollDispatcher(EventPoll& poll) +GlibPollDispatcher::GlibPollDispatcher() { - mChannel = g_io_channel_unix_new(poll.getPollFD()); + mChannel = g_io_channel_unix_new(mPoll.getPollFD()); - auto dispatchCallback = [&]() { - poll.dispatchIteration(0); + auto dispatchCallback = [this]() { + mPoll.dispatchIteration(0); }; auto cCallback = [](GIOChannel*, GIOCondition, gpointer data) -> gboolean { - getCallbackFromPointer(data)(); + utils::getCallbackFromPointer(data)(); return TRUE; }; @@ -46,8 +46,8 @@ GlibPollDispatcher::GlibPollDispatcher(EventPoll& poll) G_PRIORITY_DEFAULT, G_IO_IN, cCallback, - createCallbackWrapper(dispatchCallback, mGuard.spawn()), - &deleteCallbackWrapper); + utils::createCallbackWrapper(dispatchCallback, mGuard.spawn()), + &utils::deleteCallbackWrapper); } GlibPollDispatcher::~GlibPollDispatcher() @@ -57,5 +57,10 @@ GlibPollDispatcher::~GlibPollDispatcher() // mGuard destructor will wait for full unregister of dispatchCallback } -} // namespace utils +EventPoll& GlibPollDispatcher::getPoll() +{ + return mPoll; +} + +} // namespace epoll } // namespace vasum diff --git a/common/utils/glib-poll-dispatcher.hpp b/common/epoll/glib-poll-dispatcher.hpp similarity index 80% rename from common/utils/glib-poll-dispatcher.hpp rename to common/epoll/glib-poll-dispatcher.hpp index 07da0c3..cf300bb 100644 --- a/common/utils/glib-poll-dispatcher.hpp +++ b/common/epoll/glib-poll-dispatcher.hpp @@ -22,32 +22,35 @@ * @brief glib epoll dispatcher */ -#ifndef COMMON_UTILS_GLIB_POLL_DISPATCHER_HPP -#define COMMON_UTILS_GLIB_POLL_DISPATCHER_HPP +#ifndef COMMON_EPOLL_GLIB_POLL_DISPATCHER_HPP +#define COMMON_EPOLL_GLIB_POLL_DISPATCHER_HPP -#include "utils/event-poll.hpp" +#include "epoll/event-poll.hpp" #include "utils/callback-guard.hpp" #include namespace vasum { -namespace utils { +namespace epoll { /** * Will dispatch poll events in glib thread */ class GlibPollDispatcher { public: - GlibPollDispatcher(EventPoll& poll); + GlibPollDispatcher(); ~GlibPollDispatcher(); + + EventPoll& getPoll(); private: - CallbackGuard mGuard; + EventPoll mPoll; // before mGuard! + utils::CallbackGuard mGuard; GIOChannel* mChannel; guint mWatchId; }; -} // namespace utils +} // namespace epoll } // namespace vasum #endif // COMMON_UTILS_GLIB_POLL_DISPATCHER_HPP diff --git a/common/utils/thread-poll-dispatcher.cpp b/common/epoll/thread-poll-dispatcher.cpp similarity index 73% rename from common/utils/thread-poll-dispatcher.cpp rename to common/epoll/thread-poll-dispatcher.cpp index f350587..797a8c4 100644 --- a/common/utils/thread-poll-dispatcher.cpp +++ b/common/epoll/thread-poll-dispatcher.cpp @@ -23,23 +23,22 @@ */ #include "config.hpp" -#include "utils/thread-poll-dispatcher.hpp" - -#include +#include "epoll/thread-poll-dispatcher.hpp" namespace vasum { -namespace utils { +namespace epoll { -ThreadPollDispatcher::ThreadPollDispatcher(EventPoll& poll) - : mPoll(poll) - , mThread([&]{ poll.dispatchLoop(); }) +ThreadPollDispatcher::ThreadPollDispatcher() { - auto controlCallback = [this](int, EventPoll::Events) -> bool { + auto controlCallback = [this](int, Events) -> bool { mStopEvent.receive(); return false; // break the loop }; - poll.addFD(mStopEvent.getFD(), EPOLLIN, std::move(controlCallback)); + mPoll.addFD(mStopEvent.getFD(), EPOLLIN, std::move(controlCallback)); + mThread = std::thread([this] { + mPoll.dispatchLoop(); + }); } ThreadPollDispatcher::~ThreadPollDispatcher() @@ -49,5 +48,10 @@ ThreadPollDispatcher::~ThreadPollDispatcher() mPoll.removeFD(mStopEvent.getFD()); } -} // namespace utils +EventPoll& ThreadPollDispatcher::getPoll() +{ + return mPoll; +} + +} // namespace epoll } // namespace vasum diff --git a/common/utils/thread-poll-dispatcher.hpp b/common/epoll/thread-poll-dispatcher.hpp similarity index 77% rename from common/utils/thread-poll-dispatcher.hpp rename to common/epoll/thread-poll-dispatcher.hpp index e54cb4e..af6b278 100644 --- a/common/utils/thread-poll-dispatcher.hpp +++ b/common/epoll/thread-poll-dispatcher.hpp @@ -22,31 +22,33 @@ * @brief Thread epoll dispatcher */ -#ifndef COMMON_UTILS_THREAD_POLL_DISPATCHER_HPP -#define COMMON_UTILS_THREAD_POLL_DISPATCHER_HPP +#ifndef COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP +#define COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP -#include "utils/event-poll.hpp" +#include "epoll/event-poll.hpp" #include "utils/eventfd.hpp" #include namespace vasum { -namespace utils { +namespace epoll { /** * Will dispatch poll events in a newly created thread */ class ThreadPollDispatcher { public: - ThreadPollDispatcher(EventPoll& poll); + ThreadPollDispatcher(); ~ThreadPollDispatcher(); + + EventPoll& getPoll(); private: - EventPoll& mPoll; - EventFD mStopEvent; + EventPoll mPoll; + utils::EventFD mStopEvent; std::thread mThread; }; -} // namespace utils +} // namespace epoll } // namespace vasum -#endif // COMMON_UTILS_THREAD_POLL_DISPATCHER_HPP +#endif // COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP diff --git a/tests/unit_tests/utils/ut-event-poll.cpp b/tests/unit_tests/epoll/ut-event-poll.cpp similarity index 58% rename from tests/unit_tests/utils/ut-event-poll.cpp rename to tests/unit_tests/epoll/ut-event-poll.cpp index e387393..0bcbe81 100644 --- a/tests/unit_tests/utils/ut-event-poll.cpp +++ b/tests/unit_tests/epoll/ut-event-poll.cpp @@ -26,54 +26,21 @@ #include "config.hpp" #include "ut.hpp" -#include "utils/event-poll.hpp" +#include "epoll/event-poll.hpp" #include "logger/logger.hpp" #include "ipc/internals/socket.hpp" #include "utils/latch.hpp" #include "utils/glib-loop.hpp" -#include "utils/glib-poll-dispatcher.hpp" -#include "utils/thread-poll-dispatcher.hpp" - -#include -#include +#include "epoll/glib-poll-dispatcher.hpp" +#include "epoll/thread-poll-dispatcher.hpp" using namespace vasum::utils; +using namespace vasum::epoll; using namespace vasum::ipc; namespace { const int unsigned TIMEOUT = 1000; -#define ADD_EVENT(e) {EPOLL##e, #e} -const std::map EVENT_NAMES = { - ADD_EVENT(IN), - ADD_EVENT(OUT), - ADD_EVENT(ERR), - ADD_EVENT(HUP), - ADD_EVENT(RDHUP), -}; -#undef ADD_EVENT - -std::string strEvents(EventPoll::Events events) -{ - if (events == 0) { - return ""; - } - std::ostringstream ss; - for (const auto& p : EVENT_NAMES) { - if (events & p.first) { - ss << p.second << ", "; - events &= ~p.first; - } - } - if (events != 0) { - ss << std::hex << events; - return ss.str(); - } else { - std::string ret = ss.str(); - ret.resize(ret.size() - 2); - return ret; - } -} } // namespace @@ -87,28 +54,29 @@ BOOST_AUTO_TEST_CASE(EmptyPoll) BOOST_AUTO_TEST_CASE(ThreadedPoll) { - EventPoll poll; - ThreadPollDispatcher dispatcher(poll); + ThreadPollDispatcher dispatcher; } BOOST_AUTO_TEST_CASE(GlibPoll) { ScopedGlibLoop loop; - EventPoll poll; - GlibPollDispatcher dispatcher(poll); + GlibPollDispatcher dispatcher; } -void doSocketTest(EventPoll& poll, Latch& goodMessage, Latch& remoteClosed) +void doSocketTest(EventPoll& poll) { const std::string PATH = "/tmp/ut-poll.sock"; const std::string MESSAGE = "This is a test message"; + Latch goodMessage; + Latch remoteClosed; + Socket listen = Socket::createSocket(PATH); std::shared_ptr server; - auto serverCallback = [&](int, EventPoll::Events events) -> bool { - LOGD("Server events: " << strEvents(events)); + auto serverCallback = [&](int, Events events) -> bool { + LOGD("Server events: " << eventsToString(events)); if (events & EPOLLOUT) { server->write(MESSAGE.data(), MESSAGE.size()); @@ -118,8 +86,8 @@ void doSocketTest(EventPoll& poll, Latch& goodMessage, Latch& remoteClosed) return true; }; - auto listenCallback = [&](int, EventPoll::Events events) -> bool { - LOGD("Listen events: " << strEvents(events)); + auto listenCallback = [&](int, Events events) -> bool { + LOGD("Listen events: " << eventsToString(events)); if (events & EPOLLIN) { server = listen.accept(); poll.addFD(server->getFD(), EPOLLHUP | EPOLLRDHUP | EPOLLOUT, serverCallback); @@ -131,8 +99,8 @@ void doSocketTest(EventPoll& poll, Latch& goodMessage, Latch& remoteClosed) Socket client = Socket::connectSocket(PATH); - auto clientCallback = [&](int, EventPoll::Events events) -> bool { - LOGD("Client events: " << strEvents(events)); + auto clientCallback = [&](int, Events events) -> bool { + LOGD("Client events: " << eventsToString(events)); if (events & EPOLLIN) { std::string ret(MESSAGE.size(), 'x'); @@ -158,47 +126,33 @@ void doSocketTest(EventPoll& poll, Latch& goodMessage, Latch& remoteClosed) BOOST_AUTO_TEST_CASE(ThreadedPollSocket) { - Latch goodMessage; - Latch remoteClosed; + ThreadPollDispatcher dispatcher; - EventPoll poll; - ThreadPollDispatcher dispatcher(poll); - - doSocketTest(poll, goodMessage, remoteClosed); + doSocketTest(dispatcher.getPoll()); } BOOST_AUTO_TEST_CASE(GlibPollSocket) { - Latch goodMessage; - Latch remoteClosed; - ScopedGlibLoop loop; - EventPoll poll; - GlibPollDispatcher dispatcher(poll); + GlibPollDispatcher dispatcher; - doSocketTest(poll, goodMessage, remoteClosed); + doSocketTest(dispatcher.getPoll()); } BOOST_AUTO_TEST_CASE(PollStacking) { - Latch goodMessage; - Latch remoteClosed; + ThreadPollDispatcher dispatcher; - EventPoll outer; - EventPoll inner; + EventPoll innerPoll; - auto dispatchInner = [&](int, EventPoll::Events) -> bool { - inner.dispatchIteration(0); + auto dispatchInner = [&](int, Events) -> bool { + innerPoll.dispatchIteration(0); return true; }; - - outer.addFD(inner.getPollFD(), EPOLLIN, dispatchInner); - - ThreadPollDispatcher dispatcher(outer); - doSocketTest(inner, goodMessage, remoteClosed); - - outer.removeFD(inner.getPollFD()); + dispatcher.getPoll().addFD(innerPoll.getPollFD(), EPOLLIN, dispatchInner); + doSocketTest(innerPoll); + dispatcher.getPoll().removeFD(innerPoll.getPollFD()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index fa0de22..088f576 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -70,7 +70,6 @@ const std::string SOCKET_PATH = TEST_DIR + "/test.socket"; struct Fixture { ScopedDir mTestPathGuard; - std::string SOCKET_PATH; Fixture() : mTestPathGuard(TEST_DIR) -- 2.7.4