*/
#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"
#include <assert.h>
namespace vasum {
-namespace utils {
+namespace epoll {
EventPoll::EventPoll()
: mPollFD(::epoll_create1(EPOLL_CLOEXEC))
}
}
-} // namespace utils
+} // namespace epoll
} // namespace vasum
* @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 <functional>
#include <mutex>
#include <memory>
namespace vasum {
-namespace utils {
+namespace epoll {
class EventPoll {
public:
-
- typedef unsigned int Events;
typedef std::function<bool(int fd, Events events)> Callback;
EventPoll();
};
-} // namespace utils
+} // namespace epoll
} // namespace vasum
-#endif // COMMON_UTILS_EVENT_POLL_HPP
+#endif // COMMON_EPOLL_EVENT_POLL_HPP
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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 <sstream>
+
+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 "<NONE>";
+ }
+ 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
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * 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 <string>
+#include <sys/epoll.h> // 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
*/
#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<decltype(dispatchCallback)>(data)();
+ utils::getCallbackFromPointer<decltype(dispatchCallback)>(data)();
return TRUE;
};
G_PRIORITY_DEFAULT,
G_IO_IN,
cCallback,
- createCallbackWrapper(dispatchCallback, mGuard.spawn()),
- &deleteCallbackWrapper<decltype(dispatchCallback)>);
+ utils::createCallbackWrapper(dispatchCallback, mGuard.spawn()),
+ &utils::deleteCallbackWrapper<decltype(dispatchCallback)>);
}
GlibPollDispatcher::~GlibPollDispatcher()
// mGuard destructor will wait for full unregister of dispatchCallback
}
-} // namespace utils
+EventPoll& GlibPollDispatcher::getPoll()
+{
+ return mPoll;
+}
+
+} // namespace epoll
} // namespace vasum
* @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 <gio/gio.h>
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
*/
#include "config.hpp"
-#include "utils/thread-poll-dispatcher.hpp"
-
-#include <sys/epoll.h>
+#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()
mPoll.removeFD(mStopEvent.getFD());
}
-} // namespace utils
+EventPoll& ThreadPollDispatcher::getPoll()
+{
+ return mPoll;
+}
+
+} // namespace epoll
} // namespace vasum
* @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 <thread>
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
#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 <map>
-#include <sys/epoll.h>
+#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<EventPoll::Events, std::string> 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 "<none>";
- }
- 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
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<Socket> 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());
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);
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');
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()
struct Fixture {
ScopedDir mTestPathGuard;
- std::string SOCKET_PATH;
Fixture()
: mTestPathGuard(TEST_DIR)