From 2f1c4055b248447276cba35e1d4672f0e3d9e80a Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Mon, 23 May 2016 18:31:06 +0900 Subject: Add mainloop stop logic by using eventfd Change-Id: If175379bebd20eeb60d091284f754857f59d34a7 --- src/common/CMakeLists.txt | 1 + src/common/eventfd.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/common/eventfd.h | 49 +++++++++++++++++++++++++++++++++ src/common/mainloop.cpp | 27 ++++++++++++++++--- src/common/mainloop.h | 12 +++++++-- src/common/service.cpp | 3 ++- src/service/ocsp-service.cpp | 1 + 7 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 src/common/eventfd.cpp create mode 100644 src/common/eventfd.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index c5e965e..8143262 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -28,6 +28,7 @@ SET(${TARGET_CERT_CHECKER_COMMON}_SRCS ${COMMON_PATH}/binary-queue.cpp ${COMMON_PATH}/connection.cpp ${COMMON_PATH}/dispatcher.cpp + ${COMMON_PATH}/eventfd.cpp ${COMMON_PATH}/mainloop.cpp ${COMMON_PATH}/service.cpp ${COMMON_PATH}/socket.cpp diff --git a/src/common/eventfd.cpp b/src/common/eventfd.cpp new file mode 100644 index 0000000..1828b1f --- /dev/null +++ b/src/common/eventfd.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 eventfd.cpp + * @author Jaemin Ryu (jm77.ryu@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include +#include +#include + +#include "eventfd.h" + +namespace CCHECKER { + +EventFD::EventFD(unsigned int initval, int flags) +{ + fd = ::eventfd(initval, flags); + if (fd == -1) { + throw std::logic_error("EventFd from constructor is failed!!"); + } +} + +EventFD::~EventFD() +{ + if (fd != -1) { + ::close(fd); + } +} + +void EventFD::send() +{ + const std::uint64_t val = 1; + if (::write(fd, &val, sizeof(val)) == -1) { + throw std::logic_error("EventFd send to fd is failed!!"); + } +} + +void EventFD::receive() +{ + std::uint64_t val; + if (::read(fd, &val, sizeof(val)) == -1) { + throw std::logic_error("EventFd read to fd is failed!!"); + } +} + +} // namespace CCHECKER diff --git a/src/common/eventfd.h b/src/common/eventfd.h new file mode 100644 index 0000000..f10945f --- /dev/null +++ b/src/common/eventfd.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 eventfd.h + * @author Jaemin Ryu (jm77.ryu@samsung.com) + * @version 1.0 + * @brief + */ + +#pragma once + +#include + +namespace CCHECKER { + +class EventFD { +public: + EventFD(unsigned int initval = 0, int flags = EFD_SEMAPHORE | EFD_CLOEXEC); + ~EventFD(); + + EventFD(const EventFD&) = delete; + EventFD& operator=(const EventFD&) = delete; + + void send(); + void receive(); + + int getFd() const + { + return fd; + } + +private: + int fd; +}; + +} // namespace CCHECKER diff --git a/src/common/mainloop.cpp b/src/common/mainloop.cpp index 4e0f7dd..8ce7326 100644 --- a/src/common/mainloop.cpp +++ b/src/common/mainloop.cpp @@ -16,6 +16,7 @@ /* * @file mainloop.cpp * @author Kyungwook Tak (k.tak@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) * @version 1.0 * @brief Mainloop with epoll */ @@ -33,7 +34,8 @@ namespace CCHECKER { Mainloop::Mainloop() : m_isTimedOut(false), - m_pollfd(::epoll_create1(EPOLL_CLOEXEC)) + m_pollfd(::epoll_create1(EPOLL_CLOEXEC)), + m_stopped(false) { if (m_pollfd == -1) throw std::system_error( @@ -43,18 +45,35 @@ Mainloop::Mainloop() : Mainloop::~Mainloop() { - if (!m_isTimedOut && !m_callbacks.empty()) + if (!m_stopped && !m_isTimedOut && !m_callbacks.empty()) throw std::logic_error("mainloop registered callbacks should be empty " - "except timed out case"); + "except timed out case"); ::close(m_pollfd); } +void Mainloop::stop() +{ + m_stopped = true; + wakeupSignal.send(); +} + +void Mainloop::prepare() +{ + auto wakeupMainloop = [&](uint32_t) { + wakeupSignal.receive(); + removeEventSource(wakeupSignal.getFd()); + }; + + addEventSource(wakeupSignal.getFd(), EPOLLIN, std::move(wakeupMainloop)); +} + void Mainloop::run(int timeout) { + prepare(); m_isTimedOut = false; - while (!m_isTimedOut) { + while (!m_isTimedOut && !m_stopped) { dispatch(timeout); } diff --git a/src/common/mainloop.h b/src/common/mainloop.h index c52a115..1b3ab73 100644 --- a/src/common/mainloop.h +++ b/src/common/mainloop.h @@ -16,20 +16,24 @@ /* * @file mainloop.h * @author Kyungwook Tak (k.tak@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) * @version 1.0 - * @brief Manageloop with epoll + * @brief Mainloop with epoll */ #pragma once #include +#include #include #include +#include "common/eventfd.h" + namespace CCHECKER { class Mainloop { public: - typedef std::function Callback; + using Callback = std::function; Mainloop(); virtual ~Mainloop(); @@ -40,17 +44,21 @@ public: Mainloop &operator=(Mainloop &&) = delete; void run(int timeout); + void stop(void); void addEventSource(int fd, uint32_t event, Callback &&callback); void removeEventSource(int fd); private: void dispatch(int timeout); + void prepare(); bool m_isTimedOut; int m_pollfd; + std::atomic m_stopped; std::mutex m_mutex; std::unordered_map m_callbacks; + EventFD wakeupSignal; constexpr static size_t MAX_EPOLL_EVENTS = 32; }; diff --git a/src/common/service.cpp b/src/common/service.cpp index 6f3c46c..0c14dc2 100644 --- a/src/common/service.cpp +++ b/src/common/service.cpp @@ -65,6 +65,7 @@ void Service::start() void Service::stop() { LogInfo("Service stop!"); + m_loop.stop(); } void Service::setNewConnectionCallback(const ConnCallback &/*callback*/) @@ -85,7 +86,7 @@ void Service::setNewConnectionCallback(const ConnCallback &/*callback*/) */ m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, - [ &, fd](uint32_t event) { + [&, fd](uint32_t event) { LogDebug("read event comes in to fd[" << fd << "]"); if (m_connectionRegistry.count(fd) == 0) diff --git a/src/service/ocsp-service.cpp b/src/service/ocsp-service.cpp index 4c07fa6..5d6997d 100644 --- a/src/service/ocsp-service.cpp +++ b/src/service/ocsp-service.cpp @@ -40,6 +40,7 @@ OcspService::~OcspService() void OcspService::run(void) { m_logic.run(TIMEOUT_G_SERVICE); + this->stop(); } void OcspService::onMessageProcess(const ConnShPtr &connection) -- cgit v1.2.3