aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/utils/epoll_event_reactor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libtransport/src/utils/epoll_event_reactor.cc')
-rw-r--r--libtransport/src/utils/epoll_event_reactor.cc187
1 files changed, 187 insertions, 0 deletions
diff --git a/libtransport/src/utils/epoll_event_reactor.cc b/libtransport/src/utils/epoll_event_reactor.cc
new file mode 100644
index 000000000..0e6590d0e
--- /dev/null
+++ b/libtransport/src/utils/epoll_event_reactor.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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 <hicn/transport/utils/branch_prediction.h>
+
+#include <utils/epoll_event_reactor.h>
+#include <utils/fd_deadline_timer.h>
+
+#include <signal.h>
+#include <unistd.h>
+#include <iostream>
+
+namespace utils {
+
+EpollEventReactor::EpollEventReactor()
+ : epoll_fd_(epoll_create(20000)), run_event_loop_(true) {}
+
+EpollEventReactor::~EpollEventReactor() { close(epoll_fd_); }
+
+int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ TRANSPORT_LOGE("invalid fd %d", fd);
+ return -1;
+ }
+
+ struct epoll_event evt;
+ std::memset(&evt, 0, sizeof(evt));
+ evt.events = events;
+ evt.data.fd = fd;
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) <
+ 0)) {
+ TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+int EpollEventReactor::modFileDescriptor(int fd, uint32_t events) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ TRANSPORT_LOGE("invalid fd %d", fd);
+ return -1;
+ }
+
+ struct epoll_event evt;
+ memset(&evt, 0, sizeof(evt));
+ evt.events = events;
+ evt.data.fd = fd;
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) <
+ 0)) {
+ TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+std::size_t EpollEventReactor::mapSize() { return event_callback_map_.size(); }
+
+int EpollEventReactor::delFileDescriptor(int fd) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ TRANSPORT_LOGE("invalid fd %d", fd);
+ return -1;
+ }
+
+ struct epoll_event evt;
+ memset(&evt, 0, sizeof(evt));
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) <
+ 0)) {
+ TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ return -1;
+ }
+
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ event_callback_map_.erase(fd);
+
+ return 0;
+}
+
+void EpollEventReactor::runEventLoop(int timeout) {
+ Event evt[128];
+ int en = 0;
+ EventCallbackMap::iterator it;
+ EventCallback callback;
+
+ // evt.events = EPOLLIN | EPOLLOUT;
+ sigset_t sigset;
+ sigemptyset(&sigset);
+
+ while (run_event_loop_) {
+ memset(&evt, 0, sizeof(evt));
+
+ en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset);
+
+ if (TRANSPORT_EXPECT_FALSE(en < 0)) {
+ TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno));
+ return;
+ }
+
+ for (int i = 0; i < en; i++) {
+ if (evt[i].data.fd > 0) {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ it = event_callback_map_.find(evt[i].data.fd);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
+ TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd);
+ } else {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ callback = event_callback_map_[evt[i].data.fd];
+ }
+
+ callback(evt[i]);
+
+ // In the callback the epoll event reactor could have been stopped,
+ // then we need to check whether the event loop is still running.
+ if (TRANSPORT_EXPECT_FALSE(!run_event_loop_)) {
+ return;
+ }
+ }
+ } else {
+ TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd);
+ }
+ }
+ }
+}
+
+void EpollEventReactor::runOneEvent() {
+ Event evt;
+ int en = 0;
+ EventCallbackMap::iterator it;
+ EventCallback callback;
+
+ // evt.events = EPOLLIN | EPOLLOUT;
+ sigset_t sigset;
+ sigemptyset(&sigset);
+
+ memset(&evt, 0, sizeof(evt));
+
+ en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset);
+
+ if (TRANSPORT_EXPECT_FALSE(en < 0)) {
+ TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno));
+ return;
+ }
+
+ if (TRANSPORT_EXPECT_TRUE(evt.data.fd > 0)) {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ it = event_callback_map_.find(evt.data.fd);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
+ TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd);
+ } else {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ callback = event_callback_map_[evt.data.fd];
+ }
+
+ callback(evt);
+ }
+ } else {
+ TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd);
+ }
+}
+
+void EpollEventReactor::stop() { run_event_loop_ = false; }
+
+} // namespace utils \ No newline at end of file