From ba13bb17e949dfc7d4688fd18e08ddd9f60c988f Mon Sep 17 00:00:00 2001 From: lucas Date: Mon, 17 Jan 2022 21:46:30 +0800 Subject: [PATCH 01/25] feat(event):epoll engine supported 1. add epoll engin for event 2. update example --- Makefile | 12 +- event/Makefile | 12 +- event/config.mk | 5 +- event/engins/epoll/fd_event.cpp | 164 +++++++++++++++++ event/engins/epoll/fd_event.h | 44 +++++ event/engins/epoll/loop.cpp | 166 ++++++++++++++++++ event/engins/epoll/loop.h | 79 +++++++++ event/engins/epoll/signal_event.cpp | 140 +++++++++++++++ event/engins/epoll/signal_event.h | 46 +++++ event/engins/epoll/timer_event.cpp | 102 +++++++++++ event/engins/epoll/timer_event.h | 47 +++++ event/example/basic/Makefile | 3 +- event/example/basic/delay_delete_demo.cpp | 4 +- event/example/basic/io_example.cpp | 4 +- event/example/basic/run_in_loop_demo.cpp | 4 +- event/example/basic/run_next_seq_demo.cpp | 4 +- event/example/basic/signal_example.cpp | 4 +- .../example/basic/stdin_timer_signal_demo.cpp | 4 +- event/example/basic/timer_example.cpp | 4 +- event/loop.cpp | 13 ++ event/loop.h | 1 + 21 files changed, 845 insertions(+), 17 deletions(-) create mode 100644 event/engins/epoll/fd_event.cpp create mode 100644 event/engins/epoll/fd_event.h create mode 100644 event/engins/epoll/loop.cpp create mode 100644 event/engins/epoll/loop.h create mode 100644 event/engins/epoll/signal_event.cpp create mode 100644 event/engins/epoll/signal_event.h create mode 100644 event/engins/epoll/timer_event.cpp create mode 100644 event/engins/epoll/timer_event.h diff --git a/Makefile b/Makefile index 1697a9b..bbde94b 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,12 @@ export CC CXX CFLAGS CXXFLAGS LDFLAGS APPS_DIR app_y += base app_y += util app_y += event -app_y += eventx -app_y += network -app_y += coroutine -app_y += mqtt -app_y += log2file -app_y += main +#app_y += eventx +#app_y += network +#app_y += coroutine +#app_y += mqtt +#app_y += log2file +#app_y += main all test: $(STAGING_DIR) @for i in $(app_y); do \ diff --git a/event/Makefile b/event/Makefile index d7a9b8f..b68cd31 100644 --- a/event/Makefile +++ b/event/Makefile @@ -4,7 +4,7 @@ LIB_NAME = event LIB_NAME_EXT = - LIB_VERSION_X = 1 LIB_VERSION_Y = 0 -LIB_VERSION_Z = 0 +LIB_VERSION_Z = 1 HEAD_FILES = \ forward.h loop.h event.h \ @@ -36,6 +36,16 @@ CCXXFLAGS += -DENABLE_LIBEV=1 LIB_NAME_EXT := $(LIB_NAME_EXT)e endif +ifeq ($(ENABLE_EPOLL), yes) +SRC_FILES += \ + engins/epoll/loop.cpp \ + engins/epoll/fd_event.cpp \ + engins/epoll/signal_event.cpp \ + engins/epoll/timer_event.cpp +CCXXFLAGS += -DENABLE_EPOLL=1 +LIB_NAME_EXT := $(LIB_NAME_EXT)ep +endif + CCXXFLAGS += -DLOG_MODULE_ID='"tbox_event"' $(CXXFLAGS) ifeq ($(ENABLE_STAT), yes) diff --git a/event/config.mk b/event/config.mk index a7bd7e3..48da8d5 100644 --- a/event/config.mk +++ b/event/config.mk @@ -1,4 +1,5 @@ -ENABLE_LIBEVENT = yes -ENABLE_LIBEV = yes +#ENABLE_LIBEVENT = yes +#ENABLE_LIBEV = yes +ENABLE_EPOLL = yes ENABLE_STAT = yes diff --git a/event/engins/epoll/fd_event.cpp b/event/engins/epoll/fd_event.cpp new file mode 100644 index 0000000..46e1593 --- /dev/null +++ b/event/engins/epoll/fd_event.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include "fd_event.h" +#include "loop.h" + +namespace tbox { +namespace event { + +EpollFdEvent::EpollFdEvent(EpollLoop *wp_loop) : + wp_loop_(wp_loop), + is_inited_(false), + is_stop_after_trigger_(false), + cb_level_(0) +{ + +} + +EpollFdEvent::~EpollFdEvent() +{ + assert(cb_level_ == 0); + disable(); +} + +namespace { +short EpollEventsToLocal(short epoll_events) +{ + short ret = 0; + if ((epoll_events & EPOLLIN) || (epoll_events & EPOLLPRI)) + ret |= FdEvent::kReadEvent; + if (epoll_events & EPOLLOUT) + ret |= FdEvent::kWriteEvent; + + return ret; +} + +short LocalEventsToEpoll(short local_events) +{ + short ret = 0; + if (local_events & FdEvent::kWriteEvent) + ret |= EPOLLOUT; + + if (local_events & FdEvent::kReadEvent) + ret |= EPOLLIN; + + return ret; +} + +} + +bool EpollFdEvent::initialize(int fd, short events, Mode mode) +{ + disable(); + uint32_t epoll_events = LocalEventsToEpoll(events); + if (!fd_event_data_) + fd_event_data_ = new EventData(fd, this, EpollFdEvent::HandleEvent, epoll_events); + + + if (mode == Mode::kOneshot) + is_stop_after_trigger_ = true; + + is_inited_ = true; + return true; +} + +void EpollFdEvent::setCallback(const CallbackFunc &cb) +{ + cb_ = cb; +} + +bool EpollFdEvent::isEnabled() const +{ + if (!is_inited_) + return false; + + return is_enabled_; +} + +bool EpollFdEvent::enable() +{ + if (!is_inited_) + return false; + + if (isEnabled()) + return true; + + if (!fd_event_data_) + return false; + + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); + ev.events = fd_event_data_->events; + ev.data.ptr = static_cast(fd_event_data_); + + int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_event_data_->fd, &ev); + if (ret != 0) + return false; + + is_enabled_ = true; + return true; +} + +bool EpollFdEvent::disable() +{ + if (!is_inited_) + return false; + + if (!isEnabled()) + return true; + + if (fd_event_data_) { + epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_event_data_->fd, NULL); + delete fd_event_data_; + fd_event_data_ = nullptr; + } + + is_enabled_ = false; + return true; +} + +Loop* EpollFdEvent::getLoop() const +{ + return wp_loop_; +} + +void EpollFdEvent::HandleEvent(int fd, uint32_t events, void *obj) +{ + EpollFdEvent *self = reinterpret_cast(obj); + + if (!self) + return; + + self->onEvent(events); +} + +void EpollFdEvent::onEvent(short events) +{ +#ifdef ENABLE_STAT + using namespace std::chrono; + auto start = steady_clock::now(); +#endif + + if (cb_) { + short local_events = EpollEventsToLocal(events); + + ++cb_level_; + cb_(local_events); + --cb_level_; + + if (is_stop_after_trigger_) + disable(); + } + + auto wp_loop = wp_loop_; + wp_loop->handleNextFunc(); + +#ifdef ENABLE_STAT + uint64_t cost_us = duration_cast(steady_clock::now() - start).count(); + wp_loop->recordTimeCost(cost_us); +#endif +} + +} +} diff --git a/event/engins/epoll/fd_event.h b/event/engins/epoll/fd_event.h new file mode 100644 index 0000000..b1e6430 --- /dev/null +++ b/event/engins/epoll/fd_event.h @@ -0,0 +1,44 @@ +#ifndef TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 +#define TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 + +#include "../../fd_event.h" + +namespace tbox { +namespace event { + +class EpollLoop; +struct EventData; + +class EpollFdEvent : public FdEvent { + public: + explicit EpollFdEvent(EpollLoop *wp_loop); + virtual ~EpollFdEvent(); + + public: + virtual bool initialize(int fd, short events, Mode mode); + virtual void setCallback(const CallbackFunc &cb); + + virtual bool isEnabled() const; + virtual bool enable(); + virtual bool disable(); + + virtual Loop* getLoop() const; + + protected: + static void HandleEvent(int fd, uint32_t events, void *obj); + void onEvent(short events); + + private: + EpollLoop *wp_loop_; + bool is_inited_{ false }; + bool is_enabled_{ false }; + bool is_stop_after_trigger_ { false }; + CallbackFunc cb_; + int cb_level_{ 0 }; + EventData *fd_event_data_{ nullptr }; +}; + +} +} + +#endif //TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 diff --git a/event/engins/epoll/loop.cpp b/event/engins/epoll/loop.cpp new file mode 100644 index 0000000..2143883 --- /dev/null +++ b/event/engins/epoll/loop.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "loop.h" +#include "timer_event.h" +#include "fd_event.h" +#include "signal_event.h" + +namespace tbox { +namespace event { + +namespace { +uint64_t CurrentMilliseconds() +{ + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return t.tv_sec * 1000 + lround(t.tv_nsec / 1e6); +} +} + +EpollLoop::EpollLoop() +{ + epoll_fd_ = epoll_create1(EPOLL_CLOEXEC); +} + +EpollLoop::~EpollLoop() +{ + if (sp_exit_timer_) + delete sp_exit_timer_; + + close(epoll_fd_); +} + +void EpollLoop::onTick() +{ + if (timers_.size() <= 0) + return; + + auto now = CurrentMilliseconds(); + Timer &t = timers_.front(); + if (now < t.expired) + return; + + // The top of timer was expired + if (t.handler) + t.handler(); + + -- t.repeat; + + if (t.repeat > 0) { + t.expired = now + t.interval; + std::make_heap(timers_.begin(), timers_.end(), cmp_); ///< Just need rebuild the heap + } else { + /// Note: pop_heap and pop_back should used by paired. + std::pop_heap(timers_.begin(), timers_.end(), cmp_); + timers_.pop_back(); + } +} + +void EpollLoop::runLoop(Mode mode) +{ + std::array events; + memset(events.data(), 0 , events.size()); + valid_ = (mode == Loop::Mode::kForever); + int64_t wait_time = 0; + + if (epoll_fd_ < 0) + return; + + runThisBeforeLoop(); + + do { + /// Get the top of minimum heap + wait_time = timers_.size() > 0 ? timers_.front().expired - CurrentMilliseconds() : -1; + int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); + + onTick(); + + if (fds <= 0) + continue; + + for (int i = 0; i < fds; ++i) { + EventData *event_data = static_cast(events.at(i).data.ptr); + if (!event_data) + continue; + + if (event_data->handler) + event_data->handler(event_data->fd, events.at(i).events, event_data->obj); + } + + } while (valid_); + + runThisAfterLoop(); +} + +void EpollLoop::exitLoop(const std::chrono::milliseconds &wait_time) +{ + if (wait_time.count() == 0) { + this->valid_ = false; + } else { + sp_exit_timer_ = newTimerEvent(); + sp_exit_timer_->initialize(wait_time, Event::Mode::kOneshot); + sp_exit_timer_->setCallback(std::bind(&EpollLoop::onExitTimeup, this)); + sp_exit_timer_->enable(); + } +} + +void EpollLoop::onExitTimeup() +{ + sp_exit_timer_->disable(); + this->valid_ = false; +} + +uint64_t EpollLoop::addTimer(uint64_t interval, int repeat, std::function handler) +{ + if (repeat == 0) + return ++timer_id_; + + if (repeat < 0) + repeat = -1; + + uint64_t now = CurrentMilliseconds(); + Timer t; + + auto timer_id = ++timer_id_; + t.id = timer_id_; + t.expired = now + interval; + t.interval = interval; + t.handler = handler; + t.repeat = repeat; + + timers_.push_back(std::move(t)); + std::push_heap(timers_.begin(), timers_.end(), cmp_); + + return timer_id; +} + +void EpollLoop::delTimer(uint64_t id) +{ + std::remove_if(timers_.begin(), timers_.end(), [id](const Timer &t){ return t.id == id; }); + std::make_heap(timers_.begin(), timers_.end(), cmp_); +} + +FdEvent* EpollLoop::newFdEvent() +{ + return new EpollFdEvent(this); +} + +TimerEvent* EpollLoop::newTimerEvent() +{ + return new EpollTimerEvent(this); +} + +SignalEvent* EpollLoop::newSignalEvent() +{ + return new EpollSignalEvent(this); +} + + +} +} diff --git a/event/engins/epoll/loop.h b/event/engins/epoll/loop.h new file mode 100644 index 0000000..1901792 --- /dev/null +++ b/event/engins/epoll/loop.h @@ -0,0 +1,79 @@ +#ifndef TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 +#define TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 + +#include +#include +#include "../../common_loop.h" + +#ifndef MAX_LOOP_ENTRIES +#define MAX_LOOP_ENTRIES (1024) +#endif + +namespace tbox { +namespace event { + +typedef void(*event_handler)(int fd, uint32_t events, void *obj); + +struct EventData +{ + EventData(int f, void *o, event_handler h, uint32_t e) + : fd(f) + , obj(o) + , handler(h) + , events(e) + { } + + int fd; + void *obj; + event_handler handler; + uint32_t events; +}; + +class EpollLoop : public CommonLoop { + struct Timer + { + uint64_t interval; + uint64_t expired; + uint64_t repeat; + uint64_t id; + + std::function handler; + }; + + public: + explicit EpollLoop(); + virtual ~EpollLoop(); + + public: + virtual void runLoop(Mode mode); + virtual void exitLoop(const std::chrono::milliseconds &wait_time); + + virtual FdEvent* newFdEvent(); + virtual TimerEvent* newTimerEvent(); + virtual SignalEvent* newSignalEvent(); + + public: + int epollFd() { return epoll_fd_; } + uint64_t addTimer(uint64_t interval, int repeat, std::function handler = nullptr); + void delTimer(uint64_t id); + + protected: + void onExitTimeup(); + + private: + void onTick(); + + private: + int epoll_fd_{ -1 }; + bool valid_{ true }; + TimerEvent *sp_exit_timer_{ nullptr }; + + std::vector timers_{ }; + uint64_t timer_id_{ 0 }; + std::function cmp_{[](const Timer &x, const Timer &y){ return x.expired > y. expired; }}; +}; + +} +} + +#endif //TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 diff --git a/event/engins/epoll/signal_event.cpp b/event/engins/epoll/signal_event.cpp new file mode 100644 index 0000000..0ae82c5 --- /dev/null +++ b/event/engins/epoll/signal_event.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include "loop.h" +#include "signal_event.h" +#include "fd_event.h" + + +namespace tbox { +namespace event { + +EpollSignalEvent::EpollSignalEvent(EpollLoop *wp_loop) : + wp_loop_(wp_loop) + ,signal_fd_event_(new EpollFdEvent(wp_loop)) +{ } + +EpollSignalEvent::~EpollSignalEvent() +{ + assert(cb_level_ == 0); + disable(); + + if (signal_fd_event_) { + delete signal_fd_event_; + signal_fd_event_ = nullptr; + } +} + +bool EpollSignalEvent::initialize(int signum, Mode mode) +{ + disable(); + + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, signum); + if (sigprocmask(SIG_BLOCK, &mask, 0) == -1) + return false; + + signal_fd_ = signalfd(-1, &mask, 0); + if (signal_fd_ == -1) + return false; + + if (!signal_fd_event_->initialize(signal_fd_, FdEvent::kReadEvent, mode)) + return false; + + signal_fd_event_->setCallback(std::bind(&EpollSignalEvent::onEvent, this, std::placeholders::_1)); + + if (mode == Mode::kOneshot) is_stop_after_trigger_ = true; + + is_inited_ = true; + return true; +} + +void EpollSignalEvent::setCallback(const CallbackFunc &cb) +{ + cb_ = cb; +} + +bool EpollSignalEvent::isEnabled() const +{ + if (!is_inited_) + return false; + + return signal_fd_event_->isEnabled(); +} + +bool EpollSignalEvent::enable() +{ + if (!is_inited_) + return false; + + if (isEnabled()) + return true; + + if (!signal_fd_event_->enable()) + return false; + + return true; +} + +bool EpollSignalEvent::disable() +{ + if (!is_inited_) + return false; + + if (!isEnabled()) + return true; + + if (!signal_fd_event_->disable()) + return false; + + return true; +} + +Loop* EpollSignalEvent::getLoop() const +{ + return wp_loop_; +} + +void EpollSignalEvent::onEvent(short events) +{ +#ifdef ENABLE_STAT + using namespace std::chrono; + auto start = steady_clock::now(); +#endif + + if (!(events & FdEvent::kReadEvent)) + return; + + /// We need read the signal_fd_ if got some signals + struct signalfd_siginfo info; + if (read(signal_fd_, &info, sizeof(info)) != sizeof(info)) + return; + + /// signal number = info.ssi_signo + /// pid = info.ssi_pid + /// uid = info.ssi_uid + + if (cb_) { + ++cb_level_; + cb_(); + --cb_level_; + + if (is_stop_after_trigger_) + disable(); + } + + auto wp_loop = wp_loop_; + wp_loop->handleNextFunc(); + +#ifdef ENABLE_STAT + uint64_t cost_us = duration_cast(steady_clock::now() - start).count(); + wp_loop->recordTimeCost(cost_us); +#endif +} + +} +} diff --git a/event/engins/epoll/signal_event.h b/event/engins/epoll/signal_event.h new file mode 100644 index 0000000..dca7342 --- /dev/null +++ b/event/engins/epoll/signal_event.h @@ -0,0 +1,46 @@ +#ifndef TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 +#define TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 + +#include "../../signal_event.h" + +struct epoll_event; + +namespace tbox { +namespace event { + +class EpollLoop; +class EpollFdEvent; + +class EpollSignalEvent : public SignalEvent { + public: + explicit EpollSignalEvent(EpollLoop *wp_loop); + virtual ~EpollSignalEvent(); + + public: + virtual bool initialize(int signum, Mode mode); + virtual void setCallback(const CallbackFunc &cb); + + virtual bool isEnabled() const; + virtual bool enable(); + virtual bool disable(); + + virtual Loop* getLoop() const; + + protected: + void onEvent(short events); + + private: + EpollLoop *wp_loop_{ nullptr }; + EpollFdEvent *signal_fd_event_{ nullptr }; + + bool is_inited_{ false }; + bool is_stop_after_trigger_{ false }; + CallbackFunc cb_{ nullptr }; + int cb_level_{ 0 }; + int signal_fd_{ -1 }; +}; + +} +} + +#endif //TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 diff --git a/event/engins/epoll/timer_event.cpp b/event/engins/epoll/timer_event.cpp new file mode 100644 index 0000000..d11c8f0 --- /dev/null +++ b/event/engins/epoll/timer_event.cpp @@ -0,0 +1,102 @@ +#include +#include +#include "loop.h" +#include "timer_event.h" + +namespace tbox { +namespace event { + +EpollTimerEvent::EpollTimerEvent(EpollLoop *wp_loop) + : wp_loop_(wp_loop) +{ } + +EpollTimerEvent::~EpollTimerEvent() +{ + assert(cb_level_ == 0); + disable(); +} + +bool EpollTimerEvent::initialize(const std::chrono::milliseconds &interval, Mode mode) +{ + disable(); + + interval_ = interval; + mode_ = mode; + + is_inited_ = true; + return true; +} + +void EpollTimerEvent::setCallback(const CallbackFunc &cb) +{ + cb_ = cb; +} + +bool EpollTimerEvent::isEnabled() const +{ + if (!is_inited_) + return false; + + return is_enabled_; +} + +bool EpollTimerEvent::enable() +{ + if (!is_inited_) + return false; + + if (isEnabled()) + return true; + + if (wp_loop_) + id_ = wp_loop_->addTimer(interval_.count(), mode_ == Mode::kOneshot ? 1 : -1, [this]{ onEvent(); }); + + is_enabled_ = true; + + return true; +} + +bool EpollTimerEvent::disable() +{ + if (!is_inited_) + return false; + + if (!isEnabled()) + return true; + + if (wp_loop_) + wp_loop_->delTimer(id_); + + is_enabled_ = false; + return true; +} + +Loop* EpollTimerEvent::getLoop() const +{ + return wp_loop_; +} + +void EpollTimerEvent::onEvent() +{ +#ifdef ENABLE_STAT + using namespace std::chrono; + auto start = steady_clock::now(); +#endif + + if (cb_) { + ++cb_level_; + cb_(); + --cb_level_; + } + + auto wp_loop = wp_loop_; + wp_loop->handleNextFunc(); + +#ifdef ENABLE_STAT + uint64_t cost_us = duration_cast(steady_clock::now() - start).count(); + wp_loop->recordTimeCost(cost_us); +#endif +} + +} +} diff --git a/event/engins/epoll/timer_event.h b/event/engins/epoll/timer_event.h new file mode 100644 index 0000000..827861a --- /dev/null +++ b/event/engins/epoll/timer_event.h @@ -0,0 +1,47 @@ +#ifndef TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 +#define TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 + +#include "../../timer_event.h" + + +namespace tbox { +namespace event { + +class EpollLoop; + +class EpollTimerEvent : public TimerEvent { + public: + explicit EpollTimerEvent(EpollLoop *wp_loop); + virtual ~EpollTimerEvent(); + + public: + virtual bool initialize(const std::chrono::milliseconds &interval, Mode mode); + virtual void setCallback(const CallbackFunc &cb); + + virtual bool isEnabled() const; + virtual bool enable(); + virtual bool disable(); + + virtual Loop* getLoop() const; + + protected: + void onEvent(); + + private: + EpollLoop *wp_loop_; + bool is_inited_{ false }; + bool is_enabled_{ false }; + + std::chrono::milliseconds interval_{ 0 }; + Mode mode_{ Mode::kOneshot }; + + CallbackFunc cb_{ nullptr }; + int cb_level_{ 0 }; + + uint64_t id_{ 0 }; +}; + +} +} + +#endif //TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 diff --git a/event/example/basic/Makefile b/event/example/basic/Makefile index 8601f72..c9eb43b 100644 --- a/event/example/basic/Makefile +++ b/event/example/basic/Makefile @@ -5,7 +5,8 @@ TARGETS=io_example timer_example signal_example \ run_next_seq_demo delay_delete_demo CXXFLAGS += -ggdb -LDFLAGS += -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +#LDFLAGS += -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -ltbox_event-ep -ltbox_base -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/event/example/basic/delay_delete_demo.cpp b/event/example/basic/delay_delete_demo.cpp index b9de155..af71cf3 100644 --- a/event/example/basic/delay_delete_demo.cpp +++ b/event/example/basic/delay_delete_demo.cpp @@ -7,7 +7,7 @@ using namespace tbox::event; void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -22,6 +22,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/io_example.cpp b/event/example/basic/io_example.cpp index a30fbc0..6b31ca4 100644 --- a/event/example/basic/io_example.cpp +++ b/event/example/basic/io_example.cpp @@ -17,7 +17,7 @@ void FdCallback(int fd, short event) void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -32,6 +32,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/run_in_loop_demo.cpp b/event/example/basic/run_in_loop_demo.cpp index 167384c..0dc879d 100644 --- a/event/example/basic/run_in_loop_demo.cpp +++ b/event/example/basic/run_in_loop_demo.cpp @@ -64,7 +64,7 @@ void ThreadFunc2(Loop* wp_loop) void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -79,6 +79,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/run_next_seq_demo.cpp b/event/example/basic/run_next_seq_demo.cpp index d912e65..cbc9912 100644 --- a/event/example/basic/run_next_seq_demo.cpp +++ b/event/example/basic/run_next_seq_demo.cpp @@ -6,7 +6,7 @@ using namespace tbox::event; void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -21,6 +21,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/signal_example.cpp b/event/example/basic/signal_example.cpp index ec574bf..cf5cee4 100644 --- a/event/example/basic/signal_example.cpp +++ b/event/example/basic/signal_example.cpp @@ -14,7 +14,7 @@ void SignalCallback() void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -29,6 +29,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/stdin_timer_signal_demo.cpp b/event/example/basic/stdin_timer_signal_demo.cpp index f4bf596..ee117ba 100644 --- a/event/example/basic/stdin_timer_signal_demo.cpp +++ b/event/example/basic/stdin_timer_signal_demo.cpp @@ -75,7 +75,7 @@ void IntSignalCallback(Loop* wp_loop) void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -90,6 +90,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/example/basic/timer_example.cpp b/event/example/basic/timer_example.cpp index 82322b4..739c8d4 100644 --- a/event/example/basic/timer_example.cpp +++ b/event/example/basic/timer_example.cpp @@ -14,7 +14,7 @@ void TimerCallback() void PrintUsage(const char *process_name) { - cout << "Usage:" << process_name << " libevent|libev" << endl; + cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; } int main(int argc, char *argv[]) @@ -29,6 +29,8 @@ int main(int argc, char *argv[]) loop_engine = Loop::Engine::kLibevent; else if (string(argv[1]) == "libev") loop_engine = Loop::Engine::kLibev; + else if (string(argv[1]) == "epoll") + loop_engine = Loop::Engine::kEpoll; else { PrintUsage(argv[0]); return 0; diff --git a/event/loop.cpp b/event/loop.cpp index b4e0ead..f02d770 100644 --- a/event/loop.cpp +++ b/event/loop.cpp @@ -10,6 +10,10 @@ #include "engins/libev/loop.h" #endif +#ifdef ENABLE_EPOLL +#include "engins/epoll/loop.h" +#endif + namespace tbox { namespace event { @@ -24,6 +28,12 @@ Loop* Loop::New(Engine engine) case Engine::kLibev: return new LibevLoop; #endif + +#ifdef ENABLE_EPOLL + case Engine::kEpoll: + return new EpollLoop; +#endif + default: LogErr("Unsupport engine"); } @@ -37,6 +47,9 @@ Loop* Loop::New() #endif #ifdef ENABLE_LIBEV return new LibevLoop; +#endif +#ifdef ENABLE_EPOLL + return new EpollLoop; #endif return NULL; } diff --git a/event/loop.h b/event/loop.h index d9dbe2f..188cba5 100644 --- a/event/loop.h +++ b/event/loop.h @@ -16,6 +16,7 @@ class Loop { kLibevent, kLibev, kLibuv, + kEpoll, }; static Loop* New(); -- Gitee From acbe3a168b444fc6aec9a287986ae997cd70b734 Mon Sep 17 00:00:00 2001 From: lucas Date: Wed, 19 Jan 2022 21:36:41 +0800 Subject: [PATCH 02/25] refactor(event) : rename epoll to builtin --- event/Makefile | 14 +++---- event/config.mk | 2 +- event/engins/{epoll => builtin}/fd_event.cpp | 2 +- event/engins/{epoll => builtin}/fd_event.h | 6 +-- event/engins/{epoll => builtin}/loop.cpp | 24 ++++++------ event/engins/{epoll => builtin}/loop.h | 6 +-- .../{epoll => builtin}/signal_event.cpp | 2 +- .../engins/{epoll => builtin}/signal_event.h | 6 +-- .../engins/{epoll => builtin}/timer_event.cpp | 2 +- event/engins/{epoll => builtin}/timer_event.h | 6 +-- event/loop.cpp | 37 ++++++++----------- 11 files changed, 50 insertions(+), 57 deletions(-) rename event/engins/{epoll => builtin}/fd_event.cpp (98%) rename event/engins/{epoll => builtin}/fd_event.h (90%) rename event/engins/{epoll => builtin}/loop.cpp (84%) rename event/engins/{epoll => builtin}/loop.h (94%) rename event/engins/{epoll => builtin}/signal_event.cpp (97%) rename event/engins/{epoll => builtin}/signal_event.h (88%) rename event/engins/{epoll => builtin}/timer_event.cpp (96%) rename event/engins/{epoll => builtin}/timer_event.h (89%) diff --git a/event/Makefile b/event/Makefile index b68cd31..20584c8 100644 --- a/event/Makefile +++ b/event/Makefile @@ -36,14 +36,14 @@ CCXXFLAGS += -DENABLE_LIBEV=1 LIB_NAME_EXT := $(LIB_NAME_EXT)e endif -ifeq ($(ENABLE_EPOLL), yes) +ifeq ($(ENABLE_BUILTIN), yes) SRC_FILES += \ - engins/epoll/loop.cpp \ - engins/epoll/fd_event.cpp \ - engins/epoll/signal_event.cpp \ - engins/epoll/timer_event.cpp -CCXXFLAGS += -DENABLE_EPOLL=1 -LIB_NAME_EXT := $(LIB_NAME_EXT)ep + engins/builtin/loop.cpp \ + engins/builtin/fd_event.cpp \ + engins/builtin/signal_event.cpp \ + engins/builtin/timer_event.cpp +CCXXFLAGS += -DENABLE_BUILTIN=1 +LIB_NAME_EXT = endif CCXXFLAGS += -DLOG_MODULE_ID='"tbox_event"' $(CXXFLAGS) diff --git a/event/config.mk b/event/config.mk index 48da8d5..923f579 100644 --- a/event/config.mk +++ b/event/config.mk @@ -1,5 +1,5 @@ #ENABLE_LIBEVENT = yes #ENABLE_LIBEV = yes -ENABLE_EPOLL = yes +ENABLE_BUILTIN = yes ENABLE_STAT = yes diff --git a/event/engins/epoll/fd_event.cpp b/event/engins/builtin/fd_event.cpp similarity index 98% rename from event/engins/epoll/fd_event.cpp rename to event/engins/builtin/fd_event.cpp index 46e1593..ede4a51 100644 --- a/event/engins/epoll/fd_event.cpp +++ b/event/engins/builtin/fd_event.cpp @@ -7,7 +7,7 @@ namespace tbox { namespace event { -EpollFdEvent::EpollFdEvent(EpollLoop *wp_loop) : +EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : wp_loop_(wp_loop), is_inited_(false), is_stop_after_trigger_(false), diff --git a/event/engins/epoll/fd_event.h b/event/engins/builtin/fd_event.h similarity index 90% rename from event/engins/epoll/fd_event.h rename to event/engins/builtin/fd_event.h index b1e6430..4ec3cad 100644 --- a/event/engins/epoll/fd_event.h +++ b/event/engins/builtin/fd_event.h @@ -6,12 +6,12 @@ namespace tbox { namespace event { -class EpollLoop; +class BuiltinLoop; struct EventData; class EpollFdEvent : public FdEvent { public: - explicit EpollFdEvent(EpollLoop *wp_loop); + explicit EpollFdEvent(BuiltinLoop *wp_loop); virtual ~EpollFdEvent(); public: @@ -29,7 +29,7 @@ class EpollFdEvent : public FdEvent { void onEvent(short events); private: - EpollLoop *wp_loop_; + BuiltinLoop *wp_loop_; bool is_inited_{ false }; bool is_enabled_{ false }; bool is_stop_after_trigger_ { false }; diff --git a/event/engins/epoll/loop.cpp b/event/engins/builtin/loop.cpp similarity index 84% rename from event/engins/epoll/loop.cpp rename to event/engins/builtin/loop.cpp index 2143883..a3754d7 100644 --- a/event/engins/epoll/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -23,12 +23,12 @@ uint64_t CurrentMilliseconds() } } -EpollLoop::EpollLoop() +BuiltinLoop::BuiltinLoop() { epoll_fd_ = epoll_create1(EPOLL_CLOEXEC); } -EpollLoop::~EpollLoop() +BuiltinLoop::~BuiltinLoop() { if (sp_exit_timer_) delete sp_exit_timer_; @@ -36,7 +36,7 @@ EpollLoop::~EpollLoop() close(epoll_fd_); } -void EpollLoop::onTick() +void BuiltinLoop::onTick() { if (timers_.size() <= 0) return; @@ -62,7 +62,7 @@ void EpollLoop::onTick() } } -void EpollLoop::runLoop(Mode mode) +void BuiltinLoop::runLoop(Mode mode) { std::array events; memset(events.data(), 0 , events.size()); @@ -98,25 +98,25 @@ void EpollLoop::runLoop(Mode mode) runThisAfterLoop(); } -void EpollLoop::exitLoop(const std::chrono::milliseconds &wait_time) +void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) { if (wait_time.count() == 0) { this->valid_ = false; } else { sp_exit_timer_ = newTimerEvent(); sp_exit_timer_->initialize(wait_time, Event::Mode::kOneshot); - sp_exit_timer_->setCallback(std::bind(&EpollLoop::onExitTimeup, this)); + sp_exit_timer_->setCallback(std::bind(&BuiltinLoop::onExitTimeup, this)); sp_exit_timer_->enable(); } } -void EpollLoop::onExitTimeup() +void BuiltinLoop::onExitTimeup() { sp_exit_timer_->disable(); this->valid_ = false; } -uint64_t EpollLoop::addTimer(uint64_t interval, int repeat, std::function handler) +uint64_t BuiltinLoop::addTimer(uint64_t interval, int repeat, std::function handler) { if (repeat == 0) return ++timer_id_; @@ -140,23 +140,23 @@ uint64_t EpollLoop::addTimer(uint64_t interval, int repeat, std::function -#ifdef ENABLE_LIBEVENT +#if defined(ENABLE_LIBEVENT) #include "engins/libevent/loop.h" -#endif - -#ifdef ENABLE_LIBEV +#elif defined(ENABLE_LIBEV) #include "engins/libev/loop.h" -#endif - -#ifdef ENABLE_EPOLL -#include "engins/epoll/loop.h" +#elif defined(ENABLE_BUILTIN) +#include "engins/builtin/loop.h" +#else +#error("no engin specified!!!") #endif namespace tbox { @@ -20,36 +17,32 @@ namespace event { Loop* Loop::New(Engine engine) { switch (engine) { -#ifdef ENABLE_LIBEVENT +#if defined(ENABLE_LIBEVENT) case Engine::kLibevent: return new LibeventLoop; -#endif -#ifdef ENABLE_LIBEV +#elif defined(ENABLE_LIBEV) case Engine::kLibev: return new LibevLoop; -#endif - -#ifdef ENABLE_EPOLL +#elif defined(ENABLE_BUILTIN) case Engine::kEpoll: - return new EpollLoop; + return new BuiltinLoop; #endif default: LogErr("Unsupport engine"); } + return nullptr; } Loop* Loop::New() { -#ifdef ENABLE_LIBEVENT +#if defined(ENABLE_LIBEVENT) return new LibeventLoop; -#endif -#ifdef ENABLE_LIBEV +#elif defined(ENABLE_LIBEV) return new LibevLoop; -#endif -#ifdef ENABLE_EPOLL - return new EpollLoop; +#elif defined(ENABLE_BUILTIN) + return new BuiltinLoop; #endif return NULL; } -- Gitee From 3b385843cfe9506b0ab4de5ef376a48d70173ebd Mon Sep 17 00:00:00 2001 From: lucas Date: Wed, 19 Jan 2022 23:02:24 +0800 Subject: [PATCH 03/25] refactor(built-in) : update about timer --- event/engins/builtin/loop.cpp | 116 +++++++++++++++------------ event/engins/builtin/loop.h | 48 +++++++---- event/engins/builtin/timer_event.cpp | 4 +- event/engins/builtin/timer_event.h | 3 +- event/example/basic/Makefile | 2 +- 5 files changed, 100 insertions(+), 73 deletions(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index a3754d7..f6cf9af 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -1,15 +1,17 @@ #include #include #include -#include -#include #include +#include +#include +#include #include #include #include "loop.h" #include "timer_event.h" #include "fd_event.h" #include "signal_event.h" +#include "tbox/base/defines.h" namespace tbox { namespace event { @@ -17,9 +19,7 @@ namespace event { namespace { uint64_t CurrentMilliseconds() { - struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); - return t.tv_sec * 1000 + lround(t.tv_nsec / 1e6); + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); } } @@ -30,35 +30,41 @@ BuiltinLoop::BuiltinLoop() BuiltinLoop::~BuiltinLoop() { - if (sp_exit_timer_) - delete sp_exit_timer_; - - close(epoll_fd_); + CHECK_CLOSE_RESET_FD(epoll_fd_); + CHECK_DELETE_RESET_OBJ(sp_exit_timer_); } -void BuiltinLoop::onTick() +void BuiltinLoop::onTimeExpired() { - if (timers_.size() <= 0) + if (timer_min_heap_.size() <= 0) return; auto now = CurrentMilliseconds(); - Timer &t = timers_.front(); - if (now < t.expired) - return; - - // The top of timer was expired - if (t.handler) - t.handler(); - -- t.repeat; - - if (t.repeat > 0) { - t.expired = now + t.interval; - std::make_heap(timers_.begin(), timers_.end(), cmp_); ///< Just need rebuild the heap - } else { - /// Note: pop_heap and pop_back should used by paired. - std::pop_heap(timers_.begin(), timers_.end(), cmp_); - timers_.pop_back(); + while (timer_min_heap_.size() > 0) { + auto t = timer_min_heap_.front(); + assert(t != nullptr); + + if (now < t->expired) + return; + + // The top of timer was expired + if (t->handler) + t->handler(); + + -- t->repeat; + + // swap first element and last element + std::pop_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); + if (t->repeat > 0) { + t->expired += t->interval; + // push the last element to heap again + std::push_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); + } else { + // remove the last element + timer_min_heap_.pop_back(); + CHECK_DELETE_RESET_OBJ(t); + } } } @@ -66,7 +72,7 @@ void BuiltinLoop::runLoop(Mode mode) { std::array events; memset(events.data(), 0 , events.size()); - valid_ = (mode == Loop::Mode::kForever); + running_ = (mode == Loop::Mode::kForever); int64_t wait_time = 0; if (epoll_fd_ < 0) @@ -76,24 +82,23 @@ void BuiltinLoop::runLoop(Mode mode) do { /// Get the top of minimum heap - wait_time = timers_.size() > 0 ? timers_.front().expired - CurrentMilliseconds() : -1; + wait_time = timer_min_heap_.size() > 0 ? timer_min_heap_.front()->expired - CurrentMilliseconds() : -1; int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); - onTick(); + onTimeExpired(); if (fds <= 0) continue; for (int i = 0; i < fds; ++i) { EventData *event_data = static_cast(events.at(i).data.ptr); - if (!event_data) - continue; + assert(event_data != nullptr); if (event_data->handler) event_data->handler(event_data->fd, events.at(i).events, event_data->obj); } - } while (valid_); + } while (running_); runThisAfterLoop(); } @@ -101,7 +106,7 @@ void BuiltinLoop::runLoop(Mode mode) void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) { if (wait_time.count() == 0) { - this->valid_ = false; + running_ = false; } else { sp_exit_timer_ = newTimerEvent(); sp_exit_timer_->initialize(wait_time, Event::Mode::kOneshot); @@ -113,37 +118,44 @@ void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) void BuiltinLoop::onExitTimeup() { sp_exit_timer_->disable(); - this->valid_ = false; + running_ = false; } -uint64_t BuiltinLoop::addTimer(uint64_t interval, int repeat, std::function handler) +cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, TimerCallback handler) { if (repeat == 0) - return ++timer_id_; + return cabinet::Token(); if (repeat < 0) - repeat = -1; + repeat = std::numeric_limits::max(); - uint64_t now = CurrentMilliseconds(); - Timer t; + auto now = CurrentMilliseconds(); + Timer *t = new Timer; + assert(t != nullptr); - auto timer_id = ++timer_id_; - t.id = timer_id_; - t.expired = now + interval; - t.interval = interval; - t.handler = handler; - t.repeat = repeat; + t->expired = now + interval; + t->interval = interval; + t->handler = handler; + t->repeat = repeat; + t->token = this->timer_cabinet_.insert(t); - timers_.push_back(std::move(t)); - std::push_heap(timers_.begin(), timers_.end(), cmp_); + timer_min_heap_.push_back(t); + std::push_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); - return timer_id; + return t->token; } -void BuiltinLoop::delTimer(uint64_t id) +void BuiltinLoop::deleteTimer(const cabinet::Token& token) { - std::remove_if(timers_.begin(), timers_.end(), [id](const Timer &t){ return t.id == id; }); - std::make_heap(timers_.begin(), timers_.end(), cmp_); + std::remove_if(timer_min_heap_.begin(), timer_min_heap_.end(),[token](const Timer *t){ + if (t->token == token) { + CHECK_DELETE_RESET_OBJ(t); + return true; + } + return false; + }); + + std::make_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); } FdEvent* BuiltinLoop::newFdEvent() diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index d48ffa3..eb838d5 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -3,6 +3,7 @@ #include #include +#include "tbox/base/cabinet.hpp" #include "../../common_loop.h" #ifndef MAX_LOOP_ENTRIES @@ -30,16 +31,6 @@ struct EventData }; class BuiltinLoop : public CommonLoop { - struct Timer - { - uint64_t interval; - uint64_t expired; - uint64_t repeat; - uint64_t id; - - std::function handler; - }; - public: explicit BuiltinLoop(); virtual ~BuiltinLoop(); @@ -54,23 +45,46 @@ class BuiltinLoop : public CommonLoop { public: int epollFd() { return epoll_fd_; } - uint64_t addTimer(uint64_t interval, int repeat, std::function handler = nullptr); - void delTimer(uint64_t id); + + using TimerCallback = std::function; + cabinet::Token addTimer(uint64_t interval, int64_t repeat, TimerCallback handler = nullptr); + void deleteTimer(const cabinet::Token &); protected: void onExitTimeup(); private: - void onTick(); + void onTimeExpired(); + + private: + struct Timer + { + uint64_t interval; + uint64_t expired; + uint64_t repeat; + cabinet::Token token; + + TimerCallback handler; + }; + + struct TimerCmp + { + bool operator()(const Timer *x, const Timer *y) const + { + return x->expired > y->expired; + } + }; private: int epoll_fd_{ -1 }; - bool valid_{ true }; + bool running_{ true }; TimerEvent *sp_exit_timer_{ nullptr }; - std::vector timers_{ }; - uint64_t timer_id_{ 0 }; - std::function cmp_{[](const Timer &x, const Timer &y){ return x.expired > y. expired; }}; + //std::vector timers_{ }; + std::vector timer_min_heap_; + cabinet::Cabinet timer_cabinet_; + //uint64_t timer_id_{ 0 }; + //std::function cmp_{[](const Timer &x, const Timer &y){ return x.expired > y. expired; }}; }; } diff --git a/event/engins/builtin/timer_event.cpp b/event/engins/builtin/timer_event.cpp index 12c30ea..945fdc5 100644 --- a/event/engins/builtin/timer_event.cpp +++ b/event/engins/builtin/timer_event.cpp @@ -49,7 +49,7 @@ bool EpollTimerEvent::enable() return true; if (wp_loop_) - id_ = wp_loop_->addTimer(interval_.count(), mode_ == Mode::kOneshot ? 1 : -1, [this]{ onEvent(); }); + token_ = wp_loop_->addTimer(interval_.count(), mode_ == Mode::kOneshot ? 1 : -1, [this]{ onEvent(); }); is_enabled_ = true; @@ -65,7 +65,7 @@ bool EpollTimerEvent::disable() return true; if (wp_loop_) - wp_loop_->delTimer(id_); + wp_loop_->deleteTimer(token_); is_enabled_ = false; return true; diff --git a/event/engins/builtin/timer_event.h b/event/engins/builtin/timer_event.h index 3136723..307aabc 100644 --- a/event/engins/builtin/timer_event.h +++ b/event/engins/builtin/timer_event.h @@ -1,6 +1,7 @@ #ifndef TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 #define TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 +#include "tbox/base/cabinet.hpp" #include "../../timer_event.h" @@ -38,7 +39,7 @@ class EpollTimerEvent : public TimerEvent { CallbackFunc cb_{ nullptr }; int cb_level_{ 0 }; - uint64_t id_{ 0 }; + cabinet::Token token_; }; } diff --git a/event/example/basic/Makefile b/event/example/basic/Makefile index c9eb43b..481b24f 100644 --- a/event/example/basic/Makefile +++ b/event/example/basic/Makefile @@ -6,7 +6,7 @@ TARGETS=io_example timer_example signal_example \ CXXFLAGS += -ggdb #LDFLAGS += -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread -LDFLAGS += -ltbox_event-ep -ltbox_base -lpthread +LDFLAGS += -ltbox_event -ltbox_base -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan -- Gitee From 9102721a47ecae1ac1ea49ce1dc66986d5e6b00c Mon Sep 17 00:00:00 2001 From: lucas Date: Thu, 20 Jan 2022 21:15:35 +0800 Subject: [PATCH 04/25] fix(loop) : fix issue if max loop entries array is full --- event/engins/builtin/loop.cpp | 16 +++++++++++++--- event/engins/builtin/loop.h | 8 +++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index f6cf9af..d0e51c3 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -19,8 +19,10 @@ namespace event { namespace { uint64_t CurrentMilliseconds() { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + return std::chrono::duration_cast \ + (std::chrono::high_resolution_clock::now().time_since_epoch()).count(); } + } BuiltinLoop::BuiltinLoop() @@ -70,8 +72,9 @@ void BuiltinLoop::onTimeExpired() void BuiltinLoop::runLoop(Mode mode) { - std::array events; - memset(events.data(), 0 , events.size()); + std::vector events; + events.resize(max_loop_entries_); + running_ = (mode == Loop::Mode::kForever); int64_t wait_time = 0; @@ -98,6 +101,13 @@ void BuiltinLoop::runLoop(Mode mode) event_data->handler(event_data->fd, events.at(i).events, event_data->obj); } + /// If the receiver array size is full, increase its size + if (fds >= max_loop_entries_) { + std::vector temp_events; + temp_events.resize(++max_loop_entries_); + events.swap(temp_events); + } + } while (running_); runThisAfterLoop(); diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index eb838d5..35a64fe 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -6,8 +6,8 @@ #include "tbox/base/cabinet.hpp" #include "../../common_loop.h" -#ifndef MAX_LOOP_ENTRIES -#define MAX_LOOP_ENTRIES (1024) +#ifndef DEFAULT_MAX_LOOP_ENTRIES +#define DEFAULT_MAX_LOOP_ENTRIES (256) #endif namespace tbox { @@ -76,15 +76,13 @@ class BuiltinLoop : public CommonLoop { }; private: + int max_loop_entries_{ DEFAULT_MAX_LOOP_ENTRIES }; int epoll_fd_{ -1 }; bool running_{ true }; TimerEvent *sp_exit_timer_{ nullptr }; - //std::vector timers_{ }; std::vector timer_min_heap_; cabinet::Cabinet timer_cabinet_; - //uint64_t timer_id_{ 0 }; - //std::function cmp_{[](const Timer &x, const Timer &y){ return x.expired > y. expired; }}; }; } -- Gitee From b99cbf5ba467c213fa6f9e999549896ee06b1560 Mon Sep 17 00:00:00 2001 From: Hevake Date: Fri, 21 Jan 2022 08:25:44 +0800 Subject: [PATCH 05/25] =?UTF-8?q?=E5=AF=B9event/engins/builtin/=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/builtin/loop.cpp | 62 +++++++++++++++++------------------ event/engins/builtin/loop.h | 21 +++++------- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index d0e51c3..7d59283 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -25,9 +25,10 @@ uint64_t CurrentMilliseconds() } -BuiltinLoop::BuiltinLoop() +BuiltinLoop::BuiltinLoop() : + epoll_fd_(epoll_create1(EPOLL_CLOEXEC)) { - epoll_fd_ = epoll_create1(EPOLL_CLOEXEC); + assert(epoll_fd_ >= 0); } BuiltinLoop::~BuiltinLoop() @@ -38,12 +39,9 @@ BuiltinLoop::~BuiltinLoop() void BuiltinLoop::onTimeExpired() { - if (timer_min_heap_.size() <= 0) - return; - auto now = CurrentMilliseconds(); - while (timer_min_heap_.size() > 0) { + while (!timer_min_heap_.empty()) { auto t = timer_min_heap_.front(); assert(t != nullptr); @@ -72,20 +70,24 @@ void BuiltinLoop::onTimeExpired() void BuiltinLoop::runLoop(Mode mode) { - std::vector events; - events.resize(max_loop_entries_); - - running_ = (mode == Loop::Mode::kForever); - int64_t wait_time = 0; - if (epoll_fd_ < 0) return; + std::vector events; + events.reserve(max_loop_entries_); + runThisBeforeLoop(); + running_ = true; do { /// Get the top of minimum heap - wait_time = timer_min_heap_.size() > 0 ? timer_min_heap_.front()->expired - CurrentMilliseconds() : -1; + int64_t wait_time = -1; + if (!timer_min_heap_.empty()) { + wait_time = timer_min_heap_.front()->expired - CurrentMilliseconds(); + if (wait_time < 0) //! 有没有可能存在 expired 比当前早?如果真存在,该怎么处理? + wait_time = 0; + } + int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); onTimeExpired(); @@ -104,11 +106,12 @@ void BuiltinLoop::runLoop(Mode mode) /// If the receiver array size is full, increase its size if (fds >= max_loop_entries_) { std::vector temp_events; - temp_events.resize(++max_loop_entries_); + max_loop_entries_ = (max_loop_entries_ + max_loop_entries_ / 2); /// 按 1.5 倍增长 + temp_events.reserve(max_loop_entries_); events.swap(temp_events); } - } while (running_); + } while (running_ && (mode == Loop::Mode::kForever)); runThisAfterLoop(); } @@ -120,18 +123,12 @@ void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) } else { sp_exit_timer_ = newTimerEvent(); sp_exit_timer_->initialize(wait_time, Event::Mode::kOneshot); - sp_exit_timer_->setCallback(std::bind(&BuiltinLoop::onExitTimeup, this)); + sp_exit_timer_->setCallback([this] { running_ = false; }); sp_exit_timer_->enable(); } } -void BuiltinLoop::onExitTimeup() -{ - sp_exit_timer_->disable(); - running_ = false; -} - -cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, TimerCallback handler) +cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb) { if (repeat == 0) return cabinet::Token(); @@ -142,12 +139,12 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, TimerCa auto now = CurrentMilliseconds(); Timer *t = new Timer; assert(t != nullptr); + t->token = this->timer_cabinet_.insert(t); t->expired = now + interval; t->interval = interval; - t->handler = handler; + t->handler = cb; t->repeat = repeat; - t->token = this->timer_cabinet_.insert(t); timer_min_heap_.push_back(t); std::push_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); @@ -157,13 +154,15 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, TimerCa void BuiltinLoop::deleteTimer(const cabinet::Token& token) { - std::remove_if(timer_min_heap_.begin(), timer_min_heap_.end(),[token](const Timer *t){ - if (t->token == token) { - CHECK_DELETE_RESET_OBJ(t); - return true; + std::remove_if(timer_min_heap_.begin(), timer_min_heap_.end(), + [token] (const Timer *t) { + if (t->token == token) { + CHECK_DELETE_RESET_OBJ(t); //!FIXME: 直接删是否合适? + return true; + } + return false; } - return false; - }); + ); std::make_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); } @@ -183,6 +182,5 @@ SignalEvent* BuiltinLoop::newSignalEvent() return new EpollSignalEvent(this); } - } } diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index 35a64fe..ca992a8 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -3,6 +3,7 @@ #include #include + #include "tbox/base/cabinet.hpp" #include "../../common_loop.h" @@ -44,33 +45,27 @@ class BuiltinLoop : public CommonLoop { virtual SignalEvent* newSignalEvent(); public: - int epollFd() { return epoll_fd_; } + int epollFd() const { return epoll_fd_; } using TimerCallback = std::function; - cabinet::Token addTimer(uint64_t interval, int64_t repeat, TimerCallback handler = nullptr); + cabinet::Token addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb); void deleteTimer(const cabinet::Token &); - protected: - void onExitTimeup(); - private: void onTimeExpired(); private: - struct Timer - { + struct Timer { + cabinet::Token token; uint64_t interval; uint64_t expired; uint64_t repeat; - cabinet::Token token; TimerCallback handler; }; - struct TimerCmp - { - bool operator()(const Timer *x, const Timer *y) const - { + struct TimerCmp { + bool operator()(const Timer *x, const Timer *y) const { return x->expired > y->expired; } }; @@ -81,8 +76,8 @@ class BuiltinLoop : public CommonLoop { bool running_{ true }; TimerEvent *sp_exit_timer_{ nullptr }; - std::vector timer_min_heap_; cabinet::Cabinet timer_cabinet_; + std::vector timer_min_heap_; }; } -- Gitee From d6c0cc610bd5727ccb93475eccd75ed7e1f35147 Mon Sep 17 00:00:00 2001 From: lucas Date: Fri, 21 Jan 2022 22:18:44 +0800 Subject: [PATCH 06/25] fix(loop):fix issue about vector capacity --- event/engins/builtin/loop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index 7d59283..d3c4b76 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -88,7 +88,7 @@ void BuiltinLoop::runLoop(Mode mode) wait_time = 0; } - int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); + int fds = epoll_wait(epoll_fd_, events.data(), events.capacity(), wait_time); onTimeExpired(); -- Gitee From f677c25ca9c295794cf0a1ff708550fa8d1aa3ce Mon Sep 17 00:00:00 2001 From: lucas Date: Fri, 21 Jan 2022 22:51:11 +0800 Subject: [PATCH 07/25] fix(loop) : fix issue about resize --- event/engins/builtin/loop.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index d3c4b76..f9e6295 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -74,7 +74,14 @@ void BuiltinLoop::runLoop(Mode mode) return; std::vector events; - events.reserve(max_loop_entries_); + /* + * Why not events.reserve()? + * The reserve() method only allocates memory, but leaves it uninitialized, + * it only affects capacity(), but size() will be unchanged. + * The standard only guarantees that std::vector::data returns a pointer and [data(), data() + size()] is a valid range, + * the capacity is not concerned. So we need use resize and ensure the [data(), data() + size()] is a valid range whitch used by epoll_wait. + */ + events.resize(max_loop_entries_); runThisBeforeLoop(); @@ -84,11 +91,11 @@ void BuiltinLoop::runLoop(Mode mode) int64_t wait_time = -1; if (!timer_min_heap_.empty()) { wait_time = timer_min_heap_.front()->expired - CurrentMilliseconds(); - if (wait_time < 0) //! 有没有可能存在 expired 比当前早?如果真存在,该怎么处理? + if (wait_time < 0) //! If expired is little than now, then we consider this timer invalid and trigger it immediately. wait_time = 0; } - int fds = epoll_wait(epoll_fd_, events.data(), events.capacity(), wait_time); + int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); onTimeExpired(); @@ -103,11 +110,11 @@ void BuiltinLoop::runLoop(Mode mode) event_data->handler(event_data->fd, events.at(i).events, event_data->obj); } - /// If the receiver array size is full, increase its size + /// If the receiver array size is full, increase its size with 1.5 times. if (fds >= max_loop_entries_) { std::vector temp_events; - max_loop_entries_ = (max_loop_entries_ + max_loop_entries_ / 2); /// 按 1.5 倍增长 - temp_events.reserve(max_loop_entries_); + max_loop_entries_ = (max_loop_entries_ + max_loop_entries_ / 2); + temp_events.resize(max_loop_entries_); events.swap(temp_events); } -- Gitee From 1f00356b8c0fb32ee2bcc32c60836d0f1138e29a Mon Sep 17 00:00:00 2001 From: Hevake Date: Sat, 22 Jan 2022 06:32:38 +0800 Subject: [PATCH 08/25] fix(loop): fix issue about deleteTimer(), runLoop() --- event/engins/builtin/loop.cpp | 71 +++++++++++++++++++++-------------- event/engins/builtin/loop.h | 18 ++++----- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index f9e6295..e227678 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -13,8 +13,7 @@ #include "signal_event.h" #include "tbox/base/defines.h" -namespace tbox { -namespace event { +namespace tbox::event { namespace { uint64_t CurrentMilliseconds() @@ -37,6 +36,19 @@ BuiltinLoop::~BuiltinLoop() CHECK_DELETE_RESET_OBJ(sp_exit_timer_); } +int64_t BuiltinLoop::getWaitTime() const +{ + /// Get the top of minimum heap + int64_t wait_time = -1; + if (!timer_min_heap_.empty()) { + wait_time = timer_min_heap_.front()->expired - CurrentMilliseconds(); + if (wait_time < 0) //! If expired is little than now, then we consider this timer invalid and trigger it immediately. + wait_time = 0; + } + + return wait_time; +} + void BuiltinLoop::onTimeExpired() { auto now = CurrentMilliseconds(); @@ -46,7 +58,7 @@ void BuiltinLoop::onTimeExpired() assert(t != nullptr); if (now < t->expired) - return; + break; // The top of timer was expired if (t->handler) @@ -85,17 +97,9 @@ void BuiltinLoop::runLoop(Mode mode) runThisBeforeLoop(); - running_ = true; + keep_running_ = (mode == Loop::Mode::kForever); do { - /// Get the top of minimum heap - int64_t wait_time = -1; - if (!timer_min_heap_.empty()) { - wait_time = timer_min_heap_.front()->expired - CurrentMilliseconds(); - if (wait_time < 0) //! If expired is little than now, then we consider this timer invalid and trigger it immediately. - wait_time = 0; - } - - int fds = epoll_wait(epoll_fd_, events.data(), events.size(), wait_time); + int fds = epoll_wait(epoll_fd_, events.data(), events.size(), getWaitTime()); onTimeExpired(); @@ -112,13 +116,17 @@ void BuiltinLoop::runLoop(Mode mode) /// If the receiver array size is full, increase its size with 1.5 times. if (fds >= max_loop_entries_) { - std::vector temp_events; max_loop_entries_ = (max_loop_entries_ + max_loop_entries_ / 2); +#if 0 + std::vector temp_events; temp_events.resize(max_loop_entries_); events.swap(temp_events); +#else + events.resize(max_loop_entries_); +#endif } - } while (running_ && (mode == Loop::Mode::kForever)); + } while (keep_running_); runThisAfterLoop(); } @@ -126,16 +134,16 @@ void BuiltinLoop::runLoop(Mode mode) void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) { if (wait_time.count() == 0) { - running_ = false; + keep_running_ = false; } else { sp_exit_timer_ = newTimerEvent(); sp_exit_timer_->initialize(wait_time, Event::Mode::kOneshot); - sp_exit_timer_->setCallback([this] { running_ = false; }); + sp_exit_timer_->setCallback([this] { keep_running_ = false; }); sp_exit_timer_->enable(); } } -cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb) +cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb) { if (repeat == 0) return cabinet::Token(); @@ -144,8 +152,10 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const T repeat = std::numeric_limits::max(); auto now = CurrentMilliseconds(); + Timer *t = new Timer; assert(t != nullptr); + t->token = this->timer_cabinet_.insert(t); t->expired = now + interval; @@ -161,17 +171,23 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const T void BuiltinLoop::deleteTimer(const cabinet::Token& token) { - std::remove_if(timer_min_heap_.begin(), timer_min_heap_.end(), - [token] (const Timer *t) { - if (t->token == token) { - CHECK_DELETE_RESET_OBJ(t); //!FIXME: 直接删是否合适? - return true; - } - return false; - } - ); + auto timer = timer_cabinet_.remove(token); + if (timer == nullptr) + return; +#if 0 + timer_min_heap_.erase(timer); + std::make_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); +#else + //! If we use the above method, it is likely to disrupt order, leading to a wide range of exchanges. + //! This method will be a little better. + timer->expired = 0; std::make_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); + std::pop_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); + timer_min_heap_.pop_back(); +#endif + + runNext([timer] { delete timer; }); //! Delete later, avoid delete itself } FdEvent* BuiltinLoop::newFdEvent() @@ -190,4 +206,3 @@ SignalEvent* BuiltinLoop::newSignalEvent() } } -} diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index ca992a8..995914d 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -11,13 +11,11 @@ #define DEFAULT_MAX_LOOP_ENTRIES (256) #endif -namespace tbox { -namespace event { +namespace tbox::event { typedef void(*event_handler)(int fd, uint32_t events, void *obj); -struct EventData -{ +struct EventData { EventData(int f, void *o, event_handler h, uint32_t e) : fd(f) , obj(o) @@ -45,7 +43,7 @@ class BuiltinLoop : public CommonLoop { virtual SignalEvent* newSignalEvent(); public: - int epollFd() const { return epoll_fd_; } + inline int epollFd() const { return epoll_fd_; } using TimerCallback = std::function; cabinet::Token addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb); @@ -53,13 +51,14 @@ class BuiltinLoop : public CommonLoop { private: void onTimeExpired(); + int64_t getWaitTime() const; private: struct Timer { cabinet::Token token; - uint64_t interval; - uint64_t expired; - uint64_t repeat; + uint64_t interval = 0; + uint64_t expired = 0; + uint64_t repeat = 0; TimerCallback handler; }; @@ -73,14 +72,13 @@ class BuiltinLoop : public CommonLoop { private: int max_loop_entries_{ DEFAULT_MAX_LOOP_ENTRIES }; int epoll_fd_{ -1 }; - bool running_{ true }; + bool keep_running_{ true }; TimerEvent *sp_exit_timer_{ nullptr }; cabinet::Cabinet timer_cabinet_; std::vector timer_min_heap_; }; -} } #endif //TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 -- Gitee From 94afc484885fe4111fbedacdc011420b3e775bab Mon Sep 17 00:00:00 2001 From: Hevake Date: Sat, 22 Jan 2022 07:26:26 +0800 Subject: [PATCH 09/25] =?UTF-8?q?=E5=AF=B9event=E5=86=85=E5=BB=BA=E4=BA=8B?= =?UTF-8?q?=E6=83=85=E5=BA=93=E8=BF=9B=E8=A1=8C=E4=BC=98=E5=8C=96=EF=BC=9A?= =?UTF-8?q?=201.=E5=B0=86addTimer()=E4=B8=AD=E7=9A=84repeat=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E7=94=B1=20int64=5Ft=20=E6=94=B9=E6=88=90=20uint64=5F?= =?UTF-8?q?t;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/defines.h | 9 ++++++++ event/Makefile | 2 +- event/engins/builtin/loop.cpp | 33 +++++++++++++--------------- event/engins/builtin/loop.h | 14 ++++++------ event/engins/builtin/timer_event.cpp | 2 +- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/base/defines.h b/base/defines.h index 321990d..128d941 100644 --- a/base/defines.h +++ b/base/defines.h @@ -44,4 +44,13 @@ swap(tmp); \ } +//! 条件预加载宏 +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif + #endif //TBOX_BASE_DEFINES_H_20171030 diff --git a/event/Makefile b/event/Makefile index 20584c8..db07a9f 100644 --- a/event/Makefile +++ b/event/Makefile @@ -43,7 +43,7 @@ SRC_FILES += \ engins/builtin/signal_event.cpp \ engins/builtin/timer_event.cpp CCXXFLAGS += -DENABLE_BUILTIN=1 -LIB_NAME_EXT = +LIB_NAME_EXT := endif CCXXFLAGS += -DLOG_MODULE_ID='"tbox_event"' $(CXXFLAGS) diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index e227678..32dfdc4 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -61,21 +61,22 @@ void BuiltinLoop::onTimeExpired() break; // The top of timer was expired - if (t->handler) - t->handler(); - - -- t->repeat; + if (t->cb) + t->cb(); // swap first element and last element std::pop_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); - if (t->repeat > 0) { - t->expired += t->interval; - // push the last element to heap again - std::push_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); - } else { + if (unlikely(t->repeat == 1)) { // remove the last element timer_min_heap_.pop_back(); + timer_cabinet_.remove(t->token); CHECK_DELETE_RESET_OBJ(t); + } else { + t->expired += t->interval; + // push the last element to heap again + std::push_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); + if (t->repeat != 0) + --t->repeat; } } } @@ -110,8 +111,8 @@ void BuiltinLoop::runLoop(Mode mode) EventData *event_data = static_cast(events.at(i).data.ptr); assert(event_data != nullptr); - if (event_data->handler) - event_data->handler(event_data->fd, events.at(i).events, event_data->obj); + if (event_data->cb) + event_data->cb(event_data->fd, events.at(i).events, event_data->obj); } /// If the receiver array size is full, increase its size with 1.5 times. @@ -143,13 +144,9 @@ void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) } } -cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb) +cabinet::Token BuiltinLoop::addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb) { - if (repeat == 0) - return cabinet::Token(); - - if (repeat < 0) - repeat = std::numeric_limits::max(); + assert(cb); auto now = CurrentMilliseconds(); @@ -160,7 +157,7 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, int64_t repeat, const Ti t->expired = now + interval; t->interval = interval; - t->handler = cb; + t->cb = cb; t->repeat = repeat; timer_min_heap_.push_back(t); diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index 995914d..4b67df6 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -13,19 +13,19 @@ namespace tbox::event { -typedef void(*event_handler)(int fd, uint32_t events, void *obj); +typedef void(*event_cb)(int fd, uint32_t events, void *obj); struct EventData { - EventData(int f, void *o, event_handler h, uint32_t e) + EventData(int f, void *o, event_cb h, uint32_t e) : fd(f) , obj(o) - , handler(h) + , cb(h) , events(e) { } int fd; void *obj; - event_handler handler; + event_cb cb; uint32_t events; }; @@ -46,8 +46,8 @@ class BuiltinLoop : public CommonLoop { inline int epollFd() const { return epoll_fd_; } using TimerCallback = std::function; - cabinet::Token addTimer(uint64_t interval, int64_t repeat, const TimerCallback &cb); - void deleteTimer(const cabinet::Token &); + cabinet::Token addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb); + void deleteTimer(const cabinet::Token &token); private: void onTimeExpired(); @@ -60,7 +60,7 @@ class BuiltinLoop : public CommonLoop { uint64_t expired = 0; uint64_t repeat = 0; - TimerCallback handler; + TimerCallback cb; }; struct TimerCmp { diff --git a/event/engins/builtin/timer_event.cpp b/event/engins/builtin/timer_event.cpp index 945fdc5..93006f5 100644 --- a/event/engins/builtin/timer_event.cpp +++ b/event/engins/builtin/timer_event.cpp @@ -49,7 +49,7 @@ bool EpollTimerEvent::enable() return true; if (wp_loop_) - token_ = wp_loop_->addTimer(interval_.count(), mode_ == Mode::kOneshot ? 1 : -1, [this]{ onEvent(); }); + token_ = wp_loop_->addTimer(interval_.count(), mode_ == Mode::kOneshot ? 1 : 0, [this]{ onEvent(); }); is_enabled_ = true; -- Gitee From 9d51703afb330af177c8d39c51cbb11792d33c67 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sat, 22 Jan 2022 08:24:22 +0800 Subject: [PATCH 10/25] removed EventData in builtin --- event/engins/builtin/fd_event.cpp | 36 +++++++++---------------------- event/engins/builtin/fd_event.h | 12 +++++++++-- event/engins/builtin/loop.cpp | 17 ++++++++------- event/engins/builtin/loop.h | 16 -------------- 4 files changed, 29 insertions(+), 52 deletions(-) diff --git a/event/engins/builtin/fd_event.cpp b/event/engins/builtin/fd_event.cpp index ede4a51..14ab434 100644 --- a/event/engins/builtin/fd_event.cpp +++ b/event/engins/builtin/fd_event.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "fd_event.h" #include "loop.h" @@ -13,7 +12,7 @@ EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : is_stop_after_trigger_(false), cb_level_(0) { - + memset(&ev_, 0, sizeof(ev_)); } EpollFdEvent::~EpollFdEvent() @@ -51,10 +50,11 @@ short LocalEventsToEpoll(short local_events) bool EpollFdEvent::initialize(int fd, short events, Mode mode) { disable(); - uint32_t epoll_events = LocalEventsToEpoll(events); - if (!fd_event_data_) - fd_event_data_ = new EventData(fd, this, EpollFdEvent::HandleEvent, epoll_events); + fd_ = fd; + memset(&ev_, 0, sizeof(ev_)); + ev_.data.ptr = static_cast(this); + ev_.events = LocalEventsToEpoll(events); if (mode == Mode::kOneshot) is_stop_after_trigger_ = true; @@ -84,15 +84,7 @@ bool EpollFdEvent::enable() if (isEnabled()) return true; - if (!fd_event_data_) - return false; - - struct epoll_event ev; - memset(&ev, 0, sizeof(ev)); - ev.events = fd_event_data_->events; - ev.data.ptr = static_cast(fd_event_data_); - - int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_event_data_->fd, &ev); + int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_, &ev_); if (ret != 0) return false; @@ -108,11 +100,7 @@ bool EpollFdEvent::disable() if (!isEnabled()) return true; - if (fd_event_data_) { - epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_event_data_->fd, NULL); - delete fd_event_data_; - fd_event_data_ = nullptr; - } + epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_, NULL); is_enabled_ = false; return true; @@ -123,14 +111,10 @@ Loop* EpollFdEvent::getLoop() const return wp_loop_; } -void EpollFdEvent::HandleEvent(int fd, uint32_t events, void *obj) +void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj) { - EpollFdEvent *self = reinterpret_cast(obj); - - if (!self) - return; - - self->onEvent(events); + EpollFdEvent *pthis = static_cast(obj); + pthis->onEvent(events); } void EpollFdEvent::onEvent(short events) diff --git a/event/engins/builtin/fd_event.h b/event/engins/builtin/fd_event.h index 4ec3cad..f47d7d5 100644 --- a/event/engins/builtin/fd_event.h +++ b/event/engins/builtin/fd_event.h @@ -3,6 +3,8 @@ #include "../../fd_event.h" +#include + namespace tbox { namespace event { @@ -24,8 +26,10 @@ class EpollFdEvent : public FdEvent { virtual Loop* getLoop() const; + public: + static void OnEventCallback(int fd, uint32_t events, void *obj); + protected: - static void HandleEvent(int fd, uint32_t events, void *obj); void onEvent(short events); private: @@ -34,8 +38,12 @@ class EpollFdEvent : public FdEvent { bool is_enabled_{ false }; bool is_stop_after_trigger_ { false }; CallbackFunc cb_; + + int fd_ = -1; + struct epoll_event ev_; + int cb_level_{ 0 }; - EventData *fd_event_data_{ nullptr }; + }; } diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index 32dfdc4..ab97022 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -1,16 +1,20 @@ #include #include +#include + +#include +#include #include + #include #include #include -#include -#include -#include + #include "loop.h" #include "timer_event.h" #include "fd_event.h" #include "signal_event.h" + #include "tbox/base/defines.h" namespace tbox::event { @@ -108,11 +112,8 @@ void BuiltinLoop::runLoop(Mode mode) continue; for (int i = 0; i < fds; ++i) { - EventData *event_data = static_cast(events.at(i).data.ptr); - assert(event_data != nullptr); - - if (event_data->cb) - event_data->cb(event_data->fd, events.at(i).events, event_data->obj); + epoll_event &ev = events.at(i); + EpollFdEvent::OnEventCallback(ev.data.fd, ev.events, ev.data.ptr); } /// If the receiver array size is full, increase its size with 1.5 times. diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index 4b67df6..2f9e3ed 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -13,22 +13,6 @@ namespace tbox::event { -typedef void(*event_cb)(int fd, uint32_t events, void *obj); - -struct EventData { - EventData(int f, void *o, event_cb h, uint32_t e) - : fd(f) - , obj(o) - , cb(h) - , events(e) - { } - - int fd; - void *obj; - event_cb cb; - uint32_t events; -}; - class BuiltinLoop : public CommonLoop { public: explicit BuiltinLoop(); -- Gitee From 1a623fc695b5234fad12deeb7737f12a07488228 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sat, 22 Jan 2022 16:30:36 +0800 Subject: [PATCH 11/25] little optimization --- event/engins/builtin/fd_event.cpp | 4 +--- event/engins/builtin/fd_event.h | 4 +--- event/engins/builtin/signal_event.cpp | 18 ++++++++---------- event/engins/builtin/signal_event.h | 4 +--- event/engins/builtin/timer_event.cpp | 4 +--- event/engins/builtin/timer_event.h | 4 +--- 6 files changed, 13 insertions(+), 25 deletions(-) diff --git a/event/engins/builtin/fd_event.cpp b/event/engins/builtin/fd_event.cpp index 14ab434..d706530 100644 --- a/event/engins/builtin/fd_event.cpp +++ b/event/engins/builtin/fd_event.cpp @@ -3,8 +3,7 @@ #include "fd_event.h" #include "loop.h" -namespace tbox { -namespace event { +namespace tbox::event { EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : wp_loop_(wp_loop), @@ -145,4 +144,3 @@ void EpollFdEvent::onEvent(short events) } } -} diff --git a/event/engins/builtin/fd_event.h b/event/engins/builtin/fd_event.h index f47d7d5..078f9a2 100644 --- a/event/engins/builtin/fd_event.h +++ b/event/engins/builtin/fd_event.h @@ -5,8 +5,7 @@ #include -namespace tbox { -namespace event { +namespace tbox::event { class BuiltinLoop; struct EventData; @@ -46,7 +45,6 @@ class EpollFdEvent : public FdEvent { }; -} } #endif //TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 diff --git a/event/engins/builtin/signal_event.cpp b/event/engins/builtin/signal_event.cpp index b700a5b..2ddad87 100644 --- a/event/engins/builtin/signal_event.cpp +++ b/event/engins/builtin/signal_event.cpp @@ -4,13 +4,14 @@ #include #include #include -#include "loop.h" + #include "signal_event.h" -#include "fd_event.h" +#include +#include "loop.h" +#include "fd_event.h" -namespace tbox { -namespace event { +namespace tbox::event { EpollSignalEvent::EpollSignalEvent(BuiltinLoop *wp_loop) : wp_loop_(wp_loop) @@ -22,10 +23,7 @@ EpollSignalEvent::~EpollSignalEvent() assert(cb_level_ == 0); disable(); - if (signal_fd_event_) { - delete signal_fd_event_; - signal_fd_event_ = nullptr; - } + CHECK_DELETE_RESET_OBJ(signal_fd_event_); } bool EpollSignalEvent::initialize(int signum, Mode mode) @@ -47,7 +45,8 @@ bool EpollSignalEvent::initialize(int signum, Mode mode) signal_fd_event_->setCallback(std::bind(&EpollSignalEvent::onEvent, this, std::placeholders::_1)); - if (mode == Mode::kOneshot) is_stop_after_trigger_ = true; + if (mode == Mode::kOneshot) + is_stop_after_trigger_ = true; is_inited_ = true; return true; @@ -137,4 +136,3 @@ void EpollSignalEvent::onEvent(short events) } } -} diff --git a/event/engins/builtin/signal_event.h b/event/engins/builtin/signal_event.h index fa45c42..8f706f2 100644 --- a/event/engins/builtin/signal_event.h +++ b/event/engins/builtin/signal_event.h @@ -5,8 +5,7 @@ struct epoll_event; -namespace tbox { -namespace event { +namespace tbox::event { class BuiltinLoop; class EpollFdEvent; @@ -40,7 +39,6 @@ class EpollSignalEvent : public SignalEvent { int signal_fd_{ -1 }; }; -} } #endif //TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 diff --git a/event/engins/builtin/timer_event.cpp b/event/engins/builtin/timer_event.cpp index 93006f5..e419553 100644 --- a/event/engins/builtin/timer_event.cpp +++ b/event/engins/builtin/timer_event.cpp @@ -3,8 +3,7 @@ #include "loop.h" #include "timer_event.h" -namespace tbox { -namespace event { +namespace tbox::event { EpollTimerEvent::EpollTimerEvent(BuiltinLoop *wp_loop) : wp_loop_(wp_loop) @@ -99,4 +98,3 @@ void EpollTimerEvent::onEvent() } } -} diff --git a/event/engins/builtin/timer_event.h b/event/engins/builtin/timer_event.h index 307aabc..43bc26c 100644 --- a/event/engins/builtin/timer_event.h +++ b/event/engins/builtin/timer_event.h @@ -5,8 +5,7 @@ #include "../../timer_event.h" -namespace tbox { -namespace event { +namespace tbox::event { class BuiltinLoop; @@ -42,7 +41,6 @@ class EpollTimerEvent : public TimerEvent { cabinet::Token token_; }; -} } #endif //TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 -- Gitee From 546992dc23661e45fa51c65fdb8ca133c331e23e Mon Sep 17 00:00:00 2001 From: lucas Date: Sat, 19 Feb 2022 15:30:34 +0000 Subject: [PATCH 12/25] fix(builtin) : fix issue about fd event Fix issue if register different event(eg: kReadEvent and kWriteEvent) with same fd that may cause some errors --- event/engins/builtin/fd_event.cpp | 252 +++++++++++++++++++++----- event/engins/builtin/fd_event.h | 16 +- event/engins/builtin/loop.cpp | 4 +- event/engins/builtin/loop.h | 28 ++- event/engins/builtin/signal_event.cpp | 5 +- event/engins/builtin/signal_event.h | 5 +- event/example/basic/io_example.cpp | 19 ++ event/forward.h | 4 +- 8 files changed, 273 insertions(+), 60 deletions(-) diff --git a/event/engins/builtin/fd_event.cpp b/event/engins/builtin/fd_event.cpp index cff9304..5a7dda5 100644 --- a/event/engins/builtin/fd_event.cpp +++ b/event/engins/builtin/fd_event.cpp @@ -1,24 +1,11 @@ #include #include +#include #include "fd_event.h" #include "loop.h" -namespace tbox::event { - -EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : - wp_loop_(wp_loop), - is_inited_(false), - is_stop_after_trigger_(false), - cb_level_(0) -{ - memset(&ev_, 0, sizeof(ev_)); -} - -EpollFdEvent::~EpollFdEvent() -{ - assert(cb_level_ == 0); - disable(); -} +namespace tbox { +namespace event { namespace { short EpollEventsToLocal(short epoll_events) @@ -46,19 +33,173 @@ short LocalEventsToEpoll(short local_events) } -bool EpollFdEvent::initialize(int fd, short events, Mode mode) +class EpollFdEventImpl { - disable(); + public: + explicit EpollFdEventImpl(BuiltinLoop *wp_loop) + : wp_loop_(wp_loop) + { + memset(&ev_, 0, sizeof(ev_)); + } - fd_ = fd; - memset(&ev_, 0, sizeof(ev_)); - ev_.data.ptr = static_cast(this); - ev_.events = LocalEventsToEpoll(events); + virtual ~EpollFdEventImpl() + { + disable(); + } + + bool initialize(int fd, short events) + { + disable(); + + fd_ = fd; + memset(&ev_, 0, sizeof(ev_)); + ev_.data.ptr = static_cast(this); + ev_.events = LocalEventsToEpoll(events); + + is_inited_ = true; + return true; + } + + inline int setCallback(const FdEvent::CallbackFunc &cb) + { + cb_index_ ++; + callbacks_.push_back(std::make_pair(cb_index_, cb)); + return cb_index_; + } + + inline bool isEnabled() const + { + if (!is_inited_) + return false; + + return is_enabled_; + } + + bool enable() + { + if (!is_inited_) + return false; + + if (isEnabled()) + return true; + + int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_, &ev_); + if (ret != 0) + return false; + + is_enabled_ = true; + return true; + } + + bool disable() + { + if (!is_inited_) + return false; + + if (!isEnabled()) + return true; + + epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_, NULL); + + is_enabled_ = false; + return true; + } + + inline void ref() { ref_count_ ++; } + inline bool noref() { return ref_count_ <= 0; } + void unref(int cb_index) + { + -- ref_count_; + using Element = std::pair; + auto is_equal_to_cb_index = [cb_index](const Element &e) -> bool + { + return e.first == cb_index; + }; + + auto result_it = std::find_if(callbacks_.begin(), callbacks_.end(), is_equal_to_cb_index); + if (result_it != callbacks_.end()) + callbacks_.erase(result_it); + } + + inline uint32_t getEvents() const + { + return EpollEventsToLocal(ev_.events); + } + + public: + static void OnEventCallback(int fd, uint32_t events, void *obj) + { + EpollFdEventImpl *self = static_cast(obj); + self->onEvent(events); + } + + protected: + void onEvent(uint32_t events) + { + short local_events = EpollEventsToLocal(events); + for (const auto &it : callbacks_) { + if (it.second) + it.second(local_events); + } + } + + private: + BuiltinLoop *wp_loop_; + bool is_inited_{ false }; + bool is_enabled_{ false }; - if (mode == Mode::kOneshot) + std::vector > callbacks_; + + int fd_ { -1 }; + struct epoll_event ev_; + + int ref_count_{ 0 }; + int cb_index_{ 0 }; +}; + +EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : + wp_loop_(wp_loop), + is_stop_after_trigger_(false), + cb_level_(0) +{ +} + +EpollFdEvent::~EpollFdEvent() +{ + assert(cb_level_ == 0); + if (impl_ != nullptr) { + impl_->unref(cb_index_); + if (impl_->noref()) { + wp_loop_->unregisterFdevent(fd_); + delete impl_; + impl_ = nullptr; + } + } +} + +bool EpollFdEvent::initialize(int fd, short events, Mode mode) +{ + if (isEnabled()) + return false; + fd_ = fd; + events_ = events; + if (mode == FdEvent::Mode::kOneshot) is_stop_after_trigger_ = true; - is_inited_ = true; + impl_ = wp_loop_->queryFdevent(fd_); + if (impl_ == nullptr) { + impl_ = new EpollFdEventImpl(wp_loop_); + assert(impl_ != nullptr); + wp_loop_->registerFdEvent(fd, impl_); + } + + impl_->ref(); + cb_index_ = impl_->setCallback( + [this](short events) { + if (events & events_) + onEvent(events); + }); + return true; } @@ -69,62 +210,79 @@ void EpollFdEvent::setCallback(const CallbackFunc &cb) bool EpollFdEvent::isEnabled() const { - if (!is_inited_) + if (nullptr == impl_) return false; - return is_enabled_; + if (!impl_->isEnabled()) + return false; + + auto event_bit = impl_->getEvents() & events_; + return event_bit != 0; //!< means impl and this obj both were enabled } bool EpollFdEvent::enable() { - if (!is_inited_) + if (impl_ == nullptr) return false; - if (isEnabled()) - return true; + uint32_t new_events = 0; + if (impl_->isEnabled()) { + uint32_t events = impl_->getEvents() & events_; + if (events == events_) + return true; - int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_, &ev_); - if (ret != 0) - return false; + impl_->disable(); + new_events = impl_->getEvents() | events_; + } else { + new_events = events_; + } - is_enabled_ = true; - return true; + impl_->initialize(fd_, new_events); + + return impl_->enable(); } bool EpollFdEvent::disable() { - if (!is_inited_) - return false; + if (nullptr == impl_) + return true; - if (!isEnabled()) + if (!impl_->isEnabled()) return true; - epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_, NULL); + uint32_t events = impl_->getEvents() & events_; + if (events == 0) + return true; - is_enabled_ = false; + impl_->disable(); + uint32_t new_events = impl_->getEvents() ^ events_; + if (new_events == 0) + return true; + + impl_->initialize(fd_, new_events); + impl_->enable(); return true; } -Loop* EpollFdEvent::getLoop() const +void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj) { - return wp_loop_; + EpollFdEventImpl::OnEventCallback(fd, events, obj); } -void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj) +Loop* EpollFdEvent::getLoop() const { - EpollFdEvent *pthis = static_cast(obj); - pthis->onEvent(events); + return wp_loop_; } + void EpollFdEvent::onEvent(short events) { wp_loop_->beginEventProcess(); if (cb_) { - short local_events = EpollEventsToLocal(events); ++cb_level_; - cb_(local_events); + cb_(events); --cb_level_; if (is_stop_after_trigger_) @@ -133,5 +291,5 @@ void EpollFdEvent::onEvent(short events) wp_loop_->endEventProcess(); } - +} } diff --git a/event/engins/builtin/fd_event.h b/event/engins/builtin/fd_event.h index 078f9a2..7406602 100644 --- a/event/engins/builtin/fd_event.h +++ b/event/engins/builtin/fd_event.h @@ -5,9 +5,11 @@ #include -namespace tbox::event { +namespace tbox { +namespace event { class BuiltinLoop; +class EpollFdEventImpl; struct EventData; class EpollFdEvent : public FdEvent { @@ -33,18 +35,18 @@ class EpollFdEvent : public FdEvent { private: BuiltinLoop *wp_loop_; - bool is_inited_{ false }; - bool is_enabled_{ false }; bool is_stop_after_trigger_ { false }; CallbackFunc cb_; - - int fd_ = -1; - struct epoll_event ev_; - int cb_level_{ 0 }; + int cb_index_{ -1 }; + int fd_ { -1 }; + uint32_t events_; + + EpollFdEventImpl *impl_{ nullptr }; }; +} } #endif //TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 diff --git a/event/engins/builtin/loop.cpp b/event/engins/builtin/loop.cpp index ab97022..0eaabbe 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/builtin/loop.cpp @@ -17,7 +17,8 @@ #include "tbox/base/defines.h" -namespace tbox::event { +namespace tbox { +namespace event { namespace { uint64_t CurrentMilliseconds() @@ -204,3 +205,4 @@ SignalEvent* BuiltinLoop::newSignalEvent() } } +} diff --git a/event/engins/builtin/loop.h b/event/engins/builtin/loop.h index 2f9e3ed..faa2957 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/builtin/loop.h @@ -3,6 +3,7 @@ #include #include +#include #include "tbox/base/cabinet.hpp" #include "../../common_loop.h" @@ -11,7 +12,10 @@ #define DEFAULT_MAX_LOOP_ENTRIES (256) #endif -namespace tbox::event { +namespace tbox { +namespace event { + +class EpollFdEventImpl; class BuiltinLoop : public CommonLoop { public: @@ -33,6 +37,25 @@ class BuiltinLoop : public CommonLoop { cabinet::Token addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb); void deleteTimer(const cabinet::Token &token); + inline void registerFdEvent(int fd, EpollFdEventImpl *fd_event) + { + fd_event_map_.insert(std::make_pair(fd, fd_event)); + } + + inline void unregisterFdevent(int fd) + { + fd_event_map_.erase(fd); + } + + inline EpollFdEventImpl *queryFdevent(int fd) + { + auto it = fd_event_map_.find(fd); + if (it != fd_event_map_.end()) + return it->second; + + return nullptr; + } + private: void onTimeExpired(); int64_t getWaitTime() const; @@ -61,8 +84,11 @@ class BuiltinLoop : public CommonLoop { cabinet::Cabinet timer_cabinet_; std::vector timer_min_heap_; + + std::unordered_map fd_event_map_; }; +} } #endif //TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 diff --git a/event/engins/builtin/signal_event.cpp b/event/engins/builtin/signal_event.cpp index f840701..ad8e594 100644 --- a/event/engins/builtin/signal_event.cpp +++ b/event/engins/builtin/signal_event.cpp @@ -11,7 +11,8 @@ #include "loop.h" #include "fd_event.h" -namespace tbox::event { +namespace tbox { +namespace event { EpollSignalEvent::EpollSignalEvent(BuiltinLoop *wp_loop) : wp_loop_(wp_loop) @@ -125,5 +126,5 @@ void EpollSignalEvent::onEvent(short events) wp_loop_->endEventProcess(); } - +} } diff --git a/event/engins/builtin/signal_event.h b/event/engins/builtin/signal_event.h index 8f706f2..b115230 100644 --- a/event/engins/builtin/signal_event.h +++ b/event/engins/builtin/signal_event.h @@ -5,7 +5,8 @@ struct epoll_event; -namespace tbox::event { +namespace tbox { +namespace event { class BuiltinLoop; class EpollFdEvent; @@ -39,6 +40,8 @@ class EpollSignalEvent : public SignalEvent { int signal_fd_{ -1 }; }; +} } #endif //TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 + diff --git a/event/example/basic/io_example.cpp b/event/example/basic/io_example.cpp index 6b31ca4..12ef435 100644 --- a/event/example/basic/io_example.cpp +++ b/event/example/basic/io_example.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,12 +10,24 @@ using namespace tbox::event; void FdCallback(int fd, short event) { + cout << "on read event" << endl; char input_buff[200]; int rsize = read(fd, input_buff, sizeof(input_buff)); input_buff[rsize - 1] = '\0'; cout << "fd: " << fd << " INPUT is [" << input_buff << "]" << endl; } +void FdWCallback(int fd, short event) +{ + char input_buff[200]; + memset(input_buff,0, sizeof(input_buff)); + cout << "on write event"<< endl << "please input data:" << endl; + cin >> input_buff; + input_buff[sizeof(input_buff) - 1] = '\0'; + write(fd, input_buff, sizeof(input_buff)); + cout << endl << "write:" << "[" << input_buff << "] to fd:" << fd << endl; +} + void PrintUsage(const char *process_name) { cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; @@ -51,9 +64,15 @@ int main(int argc, char *argv[]) sp_fd->setCallback(std::bind(FdCallback, STDIN_FILENO, _1)); sp_fd->enable(); + FdEvent* sp_fdw = sp_loop->newFdEvent(); + sp_fdw->initialize(STDIN_FILENO, FdEvent::kReadEvent, Event::Mode::kPersist); + sp_fdw->setCallback(std::bind(FdWCallback, STDIN_FILENO, _1)); + sp_fdw->enable(); + sp_loop->runLoop(Loop::Mode::kForever); delete sp_fd; + delete sp_fdw; delete sp_loop; return 0; } diff --git a/event/forward.h b/event/forward.h index 4aa55ab..ea8d872 100644 --- a/event/forward.h +++ b/event/forward.h @@ -1,13 +1,15 @@ #ifndef TBOX_EVENT_FORWARD_H_20170627 #define TBOX_EVENT_FORWARD_H_20170627 -namespace tbox::event { +namespace tbox{ +namespace event { class Loop; class FdEvent; class TimerEvent; class SignalEvent; +} } #endif //TBOX_EVENT_FORWARD_H_20170627 -- Gitee From 21c492c97a7bbceeb09da8bed057d85e316785d2 Mon Sep 17 00:00:00 2001 From: Hevake Date: Wed, 23 Feb 2022 08:14:52 +0800 Subject: [PATCH 13/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9event=EF=BC=8C=E5=B0=86?= =?UTF-8?q?Builtin=E6=9B=B4=E5=90=8D=E4=B8=BAEpoll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/Makefile | 12 ++++---- event/config.mk | 2 +- event/engins/{builtin => epoll}/fd_event.cpp | 7 +++-- event/engins/{builtin => epoll}/fd_event.h | 13 ++++----- event/engins/{builtin => epoll}/loop.cpp | 22 +++++++------- event/engins/{builtin => epoll}/loop.h | 29 +++++++++---------- .../{builtin => epoll}/signal_event.cpp | 2 +- .../engins/{builtin => epoll}/signal_event.h | 6 ++-- .../engins/{builtin => epoll}/timer_event.cpp | 6 ++-- event/engins/{builtin => epoll}/timer_event.h | 11 +++---- event/loop.cpp | 19 ++++++------ mqtt/example/basic/Makefile | 2 +- 12 files changed, 65 insertions(+), 66 deletions(-) rename event/engins/{builtin => epoll}/fd_event.cpp (97%) rename event/engins/{builtin => epoll}/fd_event.h (75%) rename event/engins/{builtin => epoll}/loop.cpp (90%) rename event/engins/{builtin => epoll}/loop.h (78%) rename event/engins/{builtin => epoll}/signal_event.cpp (97%) rename event/engins/{builtin => epoll}/signal_event.h (88%) rename event/engins/{builtin => epoll}/timer_event.cpp (93%) rename event/engins/{builtin => epoll}/timer_event.h (86%) diff --git a/event/Makefile b/event/Makefile index 7716920..c4b678b 100644 --- a/event/Makefile +++ b/event/Makefile @@ -36,13 +36,13 @@ CXXFLAGS += -DENABLE_LIBEV=1 LIB_NAME_EXT := $(LIB_NAME_EXT)e endif -ifeq ($(ENABLE_BUILTIN), yes) +ifeq ($(ENABLE_EPOLL), yes) CPP_SRC_FILES += \ - engins/builtin/loop.cpp \ - engins/builtin/fd_event.cpp \ - engins/builtin/signal_event.cpp \ - engins/builtin/timer_event.cpp -CXXFLAGS += -DENABLE_BUILTIN=1 + engins/epoll/loop.cpp \ + engins/epoll/fd_event.cpp \ + engins/epoll/signal_event.cpp \ + engins/epoll/timer_event.cpp +CXXFLAGS += -DENABLE_EPOLL=1 LIB_NAME_EXT := endif diff --git a/event/config.mk b/event/config.mk index 923f579..48da8d5 100644 --- a/event/config.mk +++ b/event/config.mk @@ -1,5 +1,5 @@ #ENABLE_LIBEVENT = yes #ENABLE_LIBEV = yes -ENABLE_BUILTIN = yes +ENABLE_EPOLL = yes ENABLE_STAT = yes diff --git a/event/engins/builtin/fd_event.cpp b/event/engins/epoll/fd_event.cpp similarity index 97% rename from event/engins/builtin/fd_event.cpp rename to event/engins/epoll/fd_event.cpp index 5a7dda5..8dfb096 100644 --- a/event/engins/builtin/fd_event.cpp +++ b/event/engins/epoll/fd_event.cpp @@ -1,6 +1,7 @@ #include #include #include + #include "fd_event.h" #include "loop.h" @@ -36,7 +37,7 @@ short LocalEventsToEpoll(short local_events) class EpollFdEventImpl { public: - explicit EpollFdEventImpl(BuiltinLoop *wp_loop) + explicit EpollFdEventImpl(EpollLoop *wp_loop) : wp_loop_(wp_loop) { memset(&ev_, 0, sizeof(ev_)); @@ -144,7 +145,7 @@ class EpollFdEventImpl } private: - BuiltinLoop *wp_loop_; + EpollLoop *wp_loop_; bool is_inited_{ false }; bool is_enabled_{ false }; @@ -157,7 +158,7 @@ class EpollFdEventImpl int cb_index_{ 0 }; }; -EpollFdEvent::EpollFdEvent(BuiltinLoop *wp_loop) : +EpollFdEvent::EpollFdEvent(EpollLoop *wp_loop) : wp_loop_(wp_loop), is_stop_after_trigger_(false), cb_level_(0) diff --git a/event/engins/builtin/fd_event.h b/event/engins/epoll/fd_event.h similarity index 75% rename from event/engins/builtin/fd_event.h rename to event/engins/epoll/fd_event.h index 7406602..b0507f0 100644 --- a/event/engins/builtin/fd_event.h +++ b/event/engins/epoll/fd_event.h @@ -1,5 +1,5 @@ -#ifndef TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 -#define TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 +#ifndef TBOX_EVENT_EPOLL_FD_EVENT_H_20220110 +#define TBOX_EVENT_EPOLL_FD_EVENT_H_20220110 #include "../../fd_event.h" @@ -8,13 +8,12 @@ namespace tbox { namespace event { -class BuiltinLoop; +class EpollLoop; class EpollFdEventImpl; -struct EventData; class EpollFdEvent : public FdEvent { public: - explicit EpollFdEvent(BuiltinLoop *wp_loop); + explicit EpollFdEvent(EpollLoop *wp_loop); virtual ~EpollFdEvent(); public: @@ -34,7 +33,7 @@ class EpollFdEvent : public FdEvent { void onEvent(short events); private: - BuiltinLoop *wp_loop_; + EpollLoop *wp_loop_; bool is_stop_after_trigger_ { false }; CallbackFunc cb_; int cb_level_{ 0 }; @@ -49,4 +48,4 @@ class EpollFdEvent : public FdEvent { } } -#endif //TBOX_EVENT_LIBEPOLL_FD_EVENT_H_20220110 +#endif //TBOX_EVENT_EPOLL_FD_EVENT_H_20220110 diff --git a/event/engins/builtin/loop.cpp b/event/engins/epoll/loop.cpp similarity index 90% rename from event/engins/builtin/loop.cpp rename to event/engins/epoll/loop.cpp index 0eaabbe..cc008ed 100644 --- a/event/engins/builtin/loop.cpp +++ b/event/engins/epoll/loop.cpp @@ -29,19 +29,19 @@ uint64_t CurrentMilliseconds() } -BuiltinLoop::BuiltinLoop() : +EpollLoop::EpollLoop() : epoll_fd_(epoll_create1(EPOLL_CLOEXEC)) { assert(epoll_fd_ >= 0); } -BuiltinLoop::~BuiltinLoop() +EpollLoop::~EpollLoop() { CHECK_CLOSE_RESET_FD(epoll_fd_); CHECK_DELETE_RESET_OBJ(sp_exit_timer_); } -int64_t BuiltinLoop::getWaitTime() const +int64_t EpollLoop::getWaitTime() const { /// Get the top of minimum heap int64_t wait_time = -1; @@ -54,7 +54,7 @@ int64_t BuiltinLoop::getWaitTime() const return wait_time; } -void BuiltinLoop::onTimeExpired() +void EpollLoop::onTimeExpired() { auto now = CurrentMilliseconds(); @@ -86,7 +86,7 @@ void BuiltinLoop::onTimeExpired() } } -void BuiltinLoop::runLoop(Mode mode) +void EpollLoop::runLoop(Mode mode) { if (epoll_fd_ < 0) return; @@ -134,7 +134,7 @@ void BuiltinLoop::runLoop(Mode mode) runThisAfterLoop(); } -void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) +void EpollLoop::exitLoop(const std::chrono::milliseconds &wait_time) { if (wait_time.count() == 0) { keep_running_ = false; @@ -146,7 +146,7 @@ void BuiltinLoop::exitLoop(const std::chrono::milliseconds &wait_time) } } -cabinet::Token BuiltinLoop::addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb) +cabinet::Token EpollLoop::addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb) { assert(cb); @@ -168,7 +168,7 @@ cabinet::Token BuiltinLoop::addTimer(uint64_t interval, uint64_t repeat, const T return t->token; } -void BuiltinLoop::deleteTimer(const cabinet::Token& token) +void EpollLoop::deleteTimer(const cabinet::Token& token) { auto timer = timer_cabinet_.remove(token); if (timer == nullptr) @@ -189,17 +189,17 @@ void BuiltinLoop::deleteTimer(const cabinet::Token& token) runNext([timer] { delete timer; }); //! Delete later, avoid delete itself } -FdEvent* BuiltinLoop::newFdEvent() +FdEvent* EpollLoop::newFdEvent() { return new EpollFdEvent(this); } -TimerEvent* BuiltinLoop::newTimerEvent() +TimerEvent* EpollLoop::newTimerEvent() { return new EpollTimerEvent(this); } -SignalEvent* BuiltinLoop::newSignalEvent() +SignalEvent* EpollLoop::newSignalEvent() { return new EpollSignalEvent(this); } diff --git a/event/engins/builtin/loop.h b/event/engins/epoll/loop.h similarity index 78% rename from event/engins/builtin/loop.h rename to event/engins/epoll/loop.h index faa2957..c1c1034 100644 --- a/event/engins/builtin/loop.h +++ b/event/engins/epoll/loop.h @@ -1,5 +1,5 @@ -#ifndef TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 -#define TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 +#ifndef TBOX_EVENT_EPOLL_LOOP_H_20220105 +#define TBOX_EVENT_EPOLL_LOOP_H_20220105 #include #include @@ -17,10 +17,10 @@ namespace event { class EpollFdEventImpl; -class BuiltinLoop : public CommonLoop { +class EpollLoop : public CommonLoop { public: - explicit BuiltinLoop(); - virtual ~BuiltinLoop(); + explicit EpollLoop(); + virtual ~EpollLoop(); public: virtual void runLoop(Mode mode); @@ -37,22 +37,18 @@ class BuiltinLoop : public CommonLoop { cabinet::Token addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb); void deleteTimer(const cabinet::Token &token); - inline void registerFdEvent(int fd, EpollFdEventImpl *fd_event) - { + inline void registerFdEvent(int fd, EpollFdEventImpl *fd_event) { fd_event_map_.insert(std::make_pair(fd, fd_event)); } - inline void unregisterFdevent(int fd) - { + inline void unregisterFdevent(int fd) { fd_event_map_.erase(fd); } - inline EpollFdEventImpl *queryFdevent(int fd) - { + inline EpollFdEventImpl *queryFdevent(int fd) const { auto it = fd_event_map_.find(fd); if (it != fd_event_map_.end()) return it->second; - return nullptr; } @@ -77,13 +73,14 @@ class BuiltinLoop : public CommonLoop { }; private: - int max_loop_entries_{ DEFAULT_MAX_LOOP_ENTRIES }; - int epoll_fd_{ -1 }; + int max_loop_entries_{ DEFAULT_MAX_LOOP_ENTRIES }; + int epoll_fd_{ -1 }; bool keep_running_{ true }; + TimerEvent *sp_exit_timer_{ nullptr }; cabinet::Cabinet timer_cabinet_; - std::vector timer_min_heap_; + std::vector timer_min_heap_; std::unordered_map fd_event_map_; }; @@ -91,4 +88,4 @@ class BuiltinLoop : public CommonLoop { } } -#endif //TBOX_EVENT_LIBEPOLL_LOOP_H_20220105 +#endif //TBOX_EVENT_EPOLL_LOOP_H_20220105 diff --git a/event/engins/builtin/signal_event.cpp b/event/engins/epoll/signal_event.cpp similarity index 97% rename from event/engins/builtin/signal_event.cpp rename to event/engins/epoll/signal_event.cpp index ad8e594..8aa9b30 100644 --- a/event/engins/builtin/signal_event.cpp +++ b/event/engins/epoll/signal_event.cpp @@ -14,7 +14,7 @@ namespace tbox { namespace event { -EpollSignalEvent::EpollSignalEvent(BuiltinLoop *wp_loop) : +EpollSignalEvent::EpollSignalEvent(EpollLoop *wp_loop) : wp_loop_(wp_loop) ,signal_fd_event_(new EpollFdEvent(wp_loop)) { } diff --git a/event/engins/builtin/signal_event.h b/event/engins/epoll/signal_event.h similarity index 88% rename from event/engins/builtin/signal_event.h rename to event/engins/epoll/signal_event.h index b115230..4792dc8 100644 --- a/event/engins/builtin/signal_event.h +++ b/event/engins/epoll/signal_event.h @@ -8,12 +8,12 @@ struct epoll_event; namespace tbox { namespace event { -class BuiltinLoop; +class EpollLoop; class EpollFdEvent; class EpollSignalEvent : public SignalEvent { public: - explicit EpollSignalEvent(BuiltinLoop *wp_loop); + explicit EpollSignalEvent(EpollLoop *wp_loop); virtual ~EpollSignalEvent(); public: @@ -30,7 +30,7 @@ class EpollSignalEvent : public SignalEvent { void onEvent(short events); private: - BuiltinLoop *wp_loop_{ nullptr }; + EpollLoop *wp_loop_{ nullptr }; EpollFdEvent *signal_fd_event_{ nullptr }; bool is_inited_{ false }; diff --git a/event/engins/builtin/timer_event.cpp b/event/engins/epoll/timer_event.cpp similarity index 93% rename from event/engins/builtin/timer_event.cpp rename to event/engins/epoll/timer_event.cpp index 9dd372a..908a4bb 100644 --- a/event/engins/builtin/timer_event.cpp +++ b/event/engins/epoll/timer_event.cpp @@ -3,9 +3,10 @@ #include "loop.h" #include "timer_event.h" -namespace tbox::event { +namespace tbox { +namespace event { -EpollTimerEvent::EpollTimerEvent(BuiltinLoop *wp_loop) +EpollTimerEvent::EpollTimerEvent(EpollLoop *wp_loop) : wp_loop_(wp_loop) { } @@ -89,3 +90,4 @@ void EpollTimerEvent::onEvent() } } +} diff --git a/event/engins/builtin/timer_event.h b/event/engins/epoll/timer_event.h similarity index 86% rename from event/engins/builtin/timer_event.h rename to event/engins/epoll/timer_event.h index 43bc26c..d84acdc 100644 --- a/event/engins/builtin/timer_event.h +++ b/event/engins/epoll/timer_event.h @@ -4,14 +4,14 @@ #include "tbox/base/cabinet.hpp" #include "../../timer_event.h" +namespace tbox { +namespace event { -namespace tbox::event { - -class BuiltinLoop; +class EpollLoop; class EpollTimerEvent : public TimerEvent { public: - explicit EpollTimerEvent(BuiltinLoop *wp_loop); + explicit EpollTimerEvent(EpollLoop *wp_loop); virtual ~EpollTimerEvent(); public: @@ -28,7 +28,7 @@ class EpollTimerEvent : public TimerEvent { void onEvent(); private: - BuiltinLoop *wp_loop_; + EpollLoop *wp_loop_; bool is_inited_{ false }; bool is_enabled_{ false }; @@ -41,6 +41,7 @@ class EpollTimerEvent : public TimerEvent { cabinet::Token token_; }; +} } #endif //TBOX_EVENT_EPOLL_TIMER_EVENT_H_20200110 diff --git a/event/loop.cpp b/event/loop.cpp index 2c70948..0b76d91 100644 --- a/event/loop.cpp +++ b/event/loop.cpp @@ -5,8 +5,8 @@ #include "engins/libevent/loop.h" #elif defined(ENABLE_LIBEV) #include "engins/libev/loop.h" -#elif defined(ENABLE_BUILTIN) -#include "engins/builtin/loop.h" +#elif defined(ENABLE_EPOLL) +#include "engins/epoll/loop.h" #else #error("no engin specified!!!") #endif @@ -17,17 +17,16 @@ namespace event { Loop* Loop::New(Engine engine) { switch (engine) { -#if defined(ENABLE_LIBEVENT) +#if defined(ENABLE_EPOLL) + case Engine::kEpoll: + return new EpollLoop; +#elif defined(ENABLE_LIBEVENT) case Engine::kLibevent: return new LibeventLoop; #elif defined(ENABLE_LIBEV) case Engine::kLibev: return new LibevLoop; -#elif defined(ENABLE_BUILTIN) - case Engine::kEpoll: - return new BuiltinLoop; #endif - default: LogErr("Unsupport engine"); } @@ -37,12 +36,12 @@ Loop* Loop::New(Engine engine) Loop* Loop::New() { -#if defined(ENABLE_LIBEVENT) +#if defined(ENABLE_EPOLL) + return new EpollLoop; +#elif defined(ENABLE_LIBEVENT) return new LibeventLoop; #elif defined(ENABLE_LIBEV) return new LibevLoop; -#elif defined(ENABLE_BUILTIN) - return new BuiltinLoop; #endif return NULL; } diff --git a/mqtt/example/basic/Makefile b/mqtt/example/basic/Makefile index 8d86ab3..c3b8f60 100644 --- a/mqtt/example/basic/Makefile +++ b/mqtt/example/basic/Makefile @@ -2,7 +2,7 @@ include ../build_env.mk TARGET := sub pub conn CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_mqtt -ltbox_event-ne -ltbox_base -levent_core -lev -lmosquitto -lpthread +LDFLAGS += -L.. -ltbox_mqtt -ltbox_event -ltbox_base -lmosquitto -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan -- Gitee From 0bfba24daa38a71903f125c3f0686e568537712b Mon Sep 17 00:00:00 2001 From: Hevake Date: Wed, 23 Feb 2022 08:43:09 +0800 Subject: [PATCH 14/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9event=E4=B8=AD=E7=9A=84?= =?UTF-8?q?io=5Fexample.cpp=E7=A4=BA=E4=BE=8B=EF=BC=8C=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E8=AF=BB=E5=86=99=E4=B8=A4=E7=A7=8D=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BD=BF=E4=B9=8B=E8=83=BD=E6=9B=B4=E5=A5=BD?= =?UTF-8?q?=E5=9C=B0=E5=B1=95=E7=A4=BAFdEvent=E7=9A=84=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/example/basic/io_example.cpp | 79 ++++++++++++++++++------------ 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/event/example/basic/io_example.cpp b/event/example/basic/io_example.cpp index 12ef435..9b0c42e 100644 --- a/event/example/basic/io_example.cpp +++ b/event/example/basic/io_example.cpp @@ -1,5 +1,11 @@ +/** + * 本示例,使用异步FdEvent替代了cout, cin的功能 + */ + #include #include +#include +#include #include #include #include @@ -8,26 +14,6 @@ using namespace std; using namespace tbox; using namespace tbox::event; -void FdCallback(int fd, short event) -{ - cout << "on read event" << endl; - char input_buff[200]; - int rsize = read(fd, input_buff, sizeof(input_buff)); - input_buff[rsize - 1] = '\0'; - cout << "fd: " << fd << " INPUT is [" << input_buff << "]" << endl; -} - -void FdWCallback(int fd, short event) -{ - char input_buff[200]; - memset(input_buff,0, sizeof(input_buff)); - cout << "on write event"<< endl << "please input data:" << endl; - cin >> input_buff; - input_buff[sizeof(input_buff) - 1] = '\0'; - write(fd, input_buff, sizeof(input_buff)); - cout << endl << "write:" << "[" << input_buff << "] to fd:" << fd << endl; -} - void PrintUsage(const char *process_name) { cout << "Usage:" << process_name << " libevent|libev|epoll" << endl; @@ -58,21 +44,52 @@ int main(int argc, char *argv[]) return 0; } - FdEvent* sp_fd = sp_loop->newFdEvent(); - sp_fd->initialize(STDIN_FILENO, FdEvent::kReadEvent, Event::Mode::kPersist); - using std::placeholders::_1; - sp_fd->setCallback(std::bind(FdCallback, STDIN_FILENO, _1)); - sp_fd->enable(); + FdEvent* sp_fd_read = sp_loop->newFdEvent(); + FdEvent* sp_fd_write = sp_loop->newFdEvent(); - FdEvent* sp_fdw = sp_loop->newFdEvent(); - sp_fdw->initialize(STDIN_FILENO, FdEvent::kReadEvent, Event::Mode::kPersist); - sp_fdw->setCallback(std::bind(FdWCallback, STDIN_FILENO, _1)); - sp_fdw->enable(); + sp_fd_read->initialize(STDIN_FILENO, FdEvent::kReadEvent, Event::Mode::kPersist); //! 可读事件一直有效 + sp_fd_write->initialize(STDOUT_FILENO, FdEvent::kWriteEvent, Event::Mode::kOneshot); //! 可写事件单次有效 + + sp_fd_read->enable(); //! 可读是常开的,可写不是 + + string send_cache; //! 发送缓存 + + //! 当终端有输入的时候 + sp_fd_read->setCallback( + [&] (short event) { + if (event & FdEvent::kReadEvent) { + char input_buff[200]; + int rsize = read(STDIN_FILENO, input_buff, sizeof(input_buff)); + input_buff[rsize - 1] = '\0'; + + stringstream ss; + ss << "INPUT " << rsize << " : " << input_buff << endl; + + send_cache += ss.str(); //! 放入到send_cache中 + sp_fd_write->enable(); //! 使能发送 + } + } + ); + + //! 当终端可以输出的时候 + sp_fd_write->setCallback( + [&] (short event) { + if (event & FdEvent::kWriteEvent) { + int wsize = write(STDOUT_FILENO, send_cache.data(), send_cache.size()); //! 尝试全量发送 + if (wsize > 0) { + send_cache.erase(0, wsize); //! 删除已发送的部分 + if (!send_cache.empty()) //! 如果没有发送完,要继续发 + sp_fd_write->enable(); + } + } + } + ); sp_loop->runLoop(Loop::Mode::kForever); - delete sp_fd; - delete sp_fdw; + delete sp_fd_read; + delete sp_fd_write; delete sp_loop; + return 0; } -- Gitee From 6674ee9e2585414b95773b2f6976efdc5eb56a90 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 15:45:18 +0800 Subject: [PATCH 15/25] =?UTF-8?q?=E8=A7=A3=E5=86=B3make=20test=E7=9A=84?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coroutine/Makefile | 2 +- event/example/basic/Makefile | 2 +- event/example/calc_game/Makefile | 2 +- eventx/Makefile | 2 +- eventx/example/thread-pool/Makefile | 2 +- main/Makefile | 2 +- main/example/01_one_app/Makefile | 2 +- main/example/02_more_than_one_apps/Makefile | 2 +- main/example/03_nc_client_and_echo_server/Makefile | 2 +- mqtt/Makefile | 2 +- network/Makefile | 2 +- network/example/buffered_fd/Makefile | 2 +- network/example/stdio_stream/Makefile | 2 +- network/example/tcp_acceptor/Makefile | 2 +- network/example/tcp_client/Makefile | 2 +- network/example/tcp_connector/Makefile | 2 +- network/example/tcp_server/Makefile | 2 +- network/example/uart/Makefile | 2 +- network/example/udp_socket/Makefile | 2 +- terminal/Makefile | 2 +- terminal/example/basic/Makefile | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/coroutine/Makefile b/coroutine/Makefile index 0340355..cd24929 100644 --- a/coroutine/Makefile +++ b/coroutine/Makefile @@ -24,7 +24,7 @@ TEST_CPP_SRC_FILES = \ broadcast_test.cpp \ condition_test.cpp \ -TEST_LDFLAGS := $(LDFLAGS) -ltbox_event-ne -ltbox_base -levent_core -lev +TEST_LDFLAGS := $(LDFLAGS) -ltbox_event -ltbox_base -levent_core -lev ENABLE_SHARED_LIB = no diff --git a/event/example/basic/Makefile b/event/example/basic/Makefile index 481b24f..06ad74f 100644 --- a/event/example/basic/Makefile +++ b/event/example/basic/Makefile @@ -5,7 +5,7 @@ TARGETS=io_example timer_example signal_example \ run_next_seq_demo delay_delete_demo CXXFLAGS += -ggdb -#LDFLAGS += -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +#LDFLAGS += -ltbox_event -ltbox_base -levent_core -lev -lpthread LDFLAGS += -ltbox_event -ltbox_base -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/event/example/calc_game/Makefile b/event/example/calc_game/Makefile index f80ec21..9a4eecb 100644 --- a/event/example/calc_game/Makefile +++ b/event/example/calc_game/Makefile @@ -2,7 +2,7 @@ include ../build_env.mk TARGET := calc_game OBJECTS := main.o game.o game_lite.o -LDFLAGS += -L.. -ltbox_event-ne -ltbox_base -levent_core -lev +LDFLAGS += -L.. -ltbox_event -ltbox_base -levent_core -lev CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/eventx/Makefile b/eventx/Makefile index c2ebbff..8ea70be 100644 --- a/eventx/Makefile +++ b/eventx/Makefile @@ -17,7 +17,7 @@ TEST_CPP_SRC_FILES = \ thread_pool_test.cpp \ timer_pool_test.cpp \ -TEST_LDFLAGS := $(LDFLAGS) -ltbox_event-ne -ltbox_base -levent_core -lev +TEST_LDFLAGS := $(LDFLAGS) -ltbox_event -ltbox_base -levent_core -lev ENABLE_SHARED_LIB = no include ../tools/lib_common.mk diff --git a/eventx/example/thread-pool/Makefile b/eventx/example/thread-pool/Makefile index a1336b0..e106c2a 100644 --- a/eventx/example/thread-pool/Makefile +++ b/eventx/example/thread-pool/Makefile @@ -3,7 +3,7 @@ include ../build_env.mk TARGET := demo OBJECTS := main.o CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/main/Makefile b/main/Makefile index 0425bd0..9dd93b6 100644 --- a/main/Makefile +++ b/main/Makefile @@ -25,7 +25,7 @@ TEST_LDFLAGS := $(LDFLAGS) \ -ltbox_terminal \ -ltbox_network \ -ltbox_eventx \ - -ltbox_event-ne \ + -ltbox_event \ -ltbox_util \ -ltbox_base \ -levent_core -lev diff --git a/main/example/01_one_app/Makefile b/main/example/01_one_app/Makefile index 3b89ec1..62f4744 100644 --- a/main/example/01_one_app/Makefile +++ b/main/example/01_one_app/Makefile @@ -7,7 +7,7 @@ CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' LDFLAGS += -L.. \ -ltbox_main \ -ltbox_eventx \ - -ltbox_event-ne \ + -ltbox_event \ -ltbox_util \ -ltbox_base \ -levent_core \ diff --git a/main/example/02_more_than_one_apps/Makefile b/main/example/02_more_than_one_apps/Makefile index 4883a4d..f780d03 100644 --- a/main/example/02_more_than_one_apps/Makefile +++ b/main/example/02_more_than_one_apps/Makefile @@ -13,7 +13,7 @@ CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' LDFLAGS += -L.. \ -ltbox_main \ -ltbox_eventx \ - -ltbox_event-ne \ + -ltbox_event \ -ltbox_util \ -ltbox_base \ -levent_core \ diff --git a/main/example/03_nc_client_and_echo_server/Makefile b/main/example/03_nc_client_and_echo_server/Makefile index 9582de0..b18cd40 100644 --- a/main/example/03_nc_client_and_echo_server/Makefile +++ b/main/example/03_nc_client_and_echo_server/Makefile @@ -12,7 +12,7 @@ CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' LDFLAGS += -L.. \ -ltbox_main \ -ltbox_eventx \ - -ltbox_event-ne \ + -ltbox_event \ -ltbox_util \ -ltbox_base \ -levent_core \ diff --git a/mqtt/Makefile b/mqtt/Makefile index d4790da..8efb1eb 100644 --- a/mqtt/Makefile +++ b/mqtt/Makefile @@ -11,7 +11,7 @@ CXXFLAGS := -DLOG_MODULE_ID='"mqtt"' $(CXXFLAGS) TEST_CPP_SRC_FILES = \ -TEST_LDFLAGS := $(LDFLAGS) -ltbox_event-ne -ltbox_base -lmosquitto -levent_core -lev +TEST_LDFLAGS := $(LDFLAGS) -ltbox_event -ltbox_base -lmosquitto -levent_core -lev ENABLE_SHARED_LIB = no diff --git a/network/Makefile b/network/Makefile index 949455e..0c75478 100644 --- a/network/Makefile +++ b/network/Makefile @@ -47,7 +47,7 @@ TEST_CPP_SRC_FILES = \ sockaddr_test.cpp \ udp_socket_test.cpp \ -TEST_LDFLAGS := $(LDFLAGS) -ltbox_event-ne -ltbox_base -levent_core -lev +TEST_LDFLAGS := $(LDFLAGS) -ltbox_event -ltbox_base -levent_core -lev ENABLE_SHARED_LIB = no diff --git a/network/example/buffered_fd/Makefile b/network/example/buffered_fd/Makefile index d9de1c4..57fd8de 100644 --- a/network/example/buffered_fd/Makefile +++ b/network/example/buffered_fd/Makefile @@ -3,7 +3,7 @@ include ../build_env.mk TARGET := io_echo OBJECTS := io_echo.o CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/network/example/stdio_stream/Makefile b/network/example/stdio_stream/Makefile index bce0cc9..ff580ba 100644 --- a/network/example/stdio_stream/Makefile +++ b/network/example/stdio_stream/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/network/example/tcp_acceptor/Makefile b/network/example/tcp_acceptor/Makefile index f1f9f59..a2352c0 100644 --- a/network/example/tcp_acceptor/Makefile +++ b/network/example/tcp_acceptor/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread TARGETS = tcp_echo tcp_nc_server CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/network/example/tcp_client/Makefile b/network/example/tcp_client/Makefile index 14431fd..061edb8 100644 --- a/network/example/tcp_client/Makefile +++ b/network/example/tcp_client/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_util -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_util -ltbox_base -levent_core -lev -lpthread TARGETS = tcp_echo tcp_nc_client tcp_hex_client CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/network/example/tcp_connector/Makefile b/network/example/tcp_connector/Makefile index b01408d..dea16c8 100644 --- a/network/example/tcp_connector/Makefile +++ b/network/example/tcp_connector/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread TARGETS = tcp_echo tcp_nc_client CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/network/example/tcp_server/Makefile b/network/example/tcp_server/Makefile index f1f9f59..a2352c0 100644 --- a/network/example/tcp_server/Makefile +++ b/network/example/tcp_server/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread TARGETS = tcp_echo tcp_nc_server CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/network/example/uart/Makefile b/network/example/uart/Makefile index e1e6f2d..495f59b 100644 --- a/network/example/uart/Makefile +++ b/network/example/uart/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan diff --git a/network/example/udp_socket/Makefile b/network/example/udp_socket/Makefile index 7007ead..2962e66 100644 --- a/network/example/udp_socket/Makefile +++ b/network/example/udp_socket/Makefile @@ -1,7 +1,7 @@ include ../build_env.mk CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_network -ltbox_eventx -ltbox_event -ltbox_base -levent_core -lev -lpthread TARGETS = send_only recv_only request respond ping_pong CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer diff --git a/terminal/Makefile b/terminal/Makefile index 72ba798..7e39803 100644 --- a/terminal/Makefile +++ b/terminal/Makefile @@ -30,7 +30,7 @@ CXXFLAGS := -DLOG_MODULE_ID='"terminal"' $(CXXFLAGS) TEST_CPP_SRC_FILES = \ impl/key_event_scanner_test.cpp \ -TEST_LDFLAGS := $(LDFLAGS) -ltbox_network -ltbox_event-ne -ltbox_util -ltbox_base -levent_core -lev +TEST_LDFLAGS := $(LDFLAGS) -ltbox_network -ltbox_event -ltbox_util -ltbox_base -levent_core -lev ENABLE_SHARED_LIB = no include ../tools/lib_common.mk diff --git a/terminal/example/basic/Makefile b/terminal/example/basic/Makefile index 8fa6149..3cdd016 100644 --- a/terminal/example/basic/Makefile +++ b/terminal/example/basic/Makefile @@ -3,7 +3,7 @@ include ../build_env.mk TARGET := demo OBJECTS := main.o CXXFLAGS += -ggdb -DLOG_MODULE_ID='"demo"' -LDFLAGS += -L.. -ltbox_terminal -ltbox_util -ltbox_network -ltbox_event-ne -ltbox_base -levent_core -lev -lpthread +LDFLAGS += -L.. -ltbox_terminal -ltbox_util -ltbox_network -ltbox_event -ltbox_base -levent_core -lev -lpthread CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer LDFLAGS += -fsanitize=address -static-libasan -- Gitee From d78a1b1a924db7600de90f4d0a96a9297ed692b4 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 15:45:56 +0800 Subject: [PATCH 16/25] =?UTF-8?q?=E8=A7=A3=E5=86=B3event=20epoll=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E8=B7=91=E4=B8=8D=E8=BF=87=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/common_loop.cpp | 5 ++++- event/common_loop_test.cpp | 30 +++++++++++++++--------------- event/engins/epoll/loop.cpp | 11 +++++++---- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/event/common_loop.cpp b/event/common_loop.cpp index afd5189..99324b3 100644 --- a/event/common_loop.cpp +++ b/event/common_loop.cpp @@ -26,6 +26,9 @@ CommonLoop::CommonLoop() : CommonLoop::~CommonLoop() { assert(cb_level_ == 0); + + std::lock_guard g(lock_); + cleanupDeferredTasks(); } bool CommonLoop::isInLoopThread() @@ -192,7 +195,7 @@ void CommonLoop::onGotRunInLoopFunc(short) //! 清理 run_in_loop_func_queue_ 与 run_next_func_queue_ 中的任务 void CommonLoop::cleanupDeferredTasks() { - int remain_loop_count = 10; //! 防止出现 runNext() 递归导致无法退出循环的问题 + int remain_loop_count = 10; //! 限定次数,防止出现 runNext() 递归导致无法退出循环的问题 while ((!run_in_loop_func_queue_.empty() || !run_next_func_queue_.empty()) && remain_loop_count-- > 0) { std::deque tasks = std::move(run_next_func_queue_); diff --git a/event/common_loop_test.cpp b/event/common_loop_test.cpp index 1539ad5..f633e0d 100644 --- a/event/common_loop_test.cpp +++ b/event/common_loop_test.cpp @@ -21,7 +21,7 @@ TEST(CommonLoop, isRunning) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); sp_timer->initialize(chrono::milliseconds(10), Event::Mode::kOneshot); bool is_run = false; @@ -50,7 +50,7 @@ TEST(CommonLoop, isInLoopThread) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); sp_timer->initialize(chrono::milliseconds(10), Event::Mode::kOneshot); bool is_timer_run = false; @@ -91,9 +91,9 @@ TEST(CommonLoop, runNextInsideLoop) TimerEvent *sp_timer2 = sp_loop->newTimerEvent(); SetScopeExitAction( [sp_loop, sp_timer1, sp_timer2]{ - delete sp_loop; - delete sp_timer1; delete sp_timer2; + delete sp_timer1; + delete sp_loop; } ); @@ -131,7 +131,7 @@ TEST(CommonLoop, runNextBeforeLoop) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); bool is_run_next_run = false; sp_loop->runNext([&] { is_run_next_run = true; }); @@ -188,9 +188,9 @@ TEST(CommonLoop, runInLoopInsideLoop) TimerEvent *sp_timer2 = sp_loop->newTimerEvent(); SetScopeExitAction( [sp_loop, sp_timer1, sp_timer2]{ - delete sp_loop; - delete sp_timer1; delete sp_timer2; + delete sp_timer1; + delete sp_loop; } ); @@ -227,7 +227,7 @@ TEST(CommonLoop, runInLoopBeforeLoop) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); bool is_run = false; sp_loop->runInLoop([&] { is_run = true; }); @@ -256,7 +256,7 @@ TEST(CommonLoop, runInLoopCrossThread) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); bool is_thread_run = false; bool is_run = false; @@ -298,9 +298,9 @@ TEST(CommonLoop, runInsideLoop) TimerEvent *sp_timer2 = sp_loop->newTimerEvent(); SetScopeExitAction( [sp_loop, sp_timer1, sp_timer2]{ - delete sp_loop; - delete sp_timer1; delete sp_timer2; + delete sp_timer1; + delete sp_loop; } ); @@ -337,7 +337,7 @@ TEST(CommonLoop, runBeforeLoop) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); bool is_run = false; sp_loop->run([&] { is_run = true; }); @@ -366,7 +366,7 @@ TEST(CommonLoop, runCrossThread) cout << "engin: " << e << endl; Loop *sp_loop = event::Loop::New(e); TimerEvent *sp_timer = sp_loop->newTimerEvent(); - SetScopeExitAction([sp_loop, sp_timer]{ delete sp_loop; delete sp_timer; }); + SetScopeExitAction([sp_loop, sp_timer]{ delete sp_timer; delete sp_loop; }); bool is_thread_run = false; bool is_run = false; @@ -407,8 +407,8 @@ TEST(CommonLoop, cleanupDeferedTask) TimerEvent *sp_timer1 = sp_loop->newTimerEvent(); SetScopeExitAction( [&]{ - delete sp_loop; delete sp_timer1; + delete sp_loop; } ); @@ -463,8 +463,8 @@ TEST(CommonLoop, runOrder) TimerEvent *sp_timer1 = sp_loop->newTimerEvent(); SetScopeExitAction( [sp_loop, sp_timer1]{ - delete sp_loop; delete sp_timer1; + delete sp_loop; } ); diff --git a/event/engins/epoll/loop.cpp b/event/engins/epoll/loop.cpp index cc008ed..caa61fb 100644 --- a/event/engins/epoll/loop.cpp +++ b/event/engins/epoll/loop.cpp @@ -65,9 +65,7 @@ void EpollLoop::onTimeExpired() if (now < t->expired) break; - // The top of timer was expired - if (t->cb) - t->cb(); + auto tobe_run = t->cb; // swap first element and last element std::pop_heap(timer_min_heap_.begin(), timer_min_heap_.end(), TimerCmp()); @@ -83,6 +81,11 @@ void EpollLoop::onTimeExpired() if (t->repeat != 0) --t->repeat; } + + //! Q: 为什么不在L68执行? + //! A: 因为要尽可能地将回调放到最后执行。否则不满足测试 TEST(TimerEvent, DisableSelfInCallback) + if (tobe_run) + tobe_run(); } } @@ -186,7 +189,7 @@ void EpollLoop::deleteTimer(const cabinet::Token& token) timer_min_heap_.pop_back(); #endif - runNext([timer] { delete timer; }); //! Delete later, avoid delete itself + run([timer] { delete timer; }); //! Delete later, avoid delete itself } FdEvent* EpollLoop::newFdEvent() -- Gitee From 0257a4a0d67cdc54a5c4432cf19b17b53913eaf7 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 17:07:05 +0800 Subject: [PATCH 17/25] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=AF=B9Epoll?= =?UTF-8?q?FdEvent=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=B9=B6=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/epoll/fd_event.cpp | 291 ++++++++------------------------ event/engins/epoll/fd_event.h | 32 ++-- event/engins/epoll/loop.cpp | 19 +++ event/engins/epoll/loop.h | 21 +-- 4 files changed, 114 insertions(+), 249 deletions(-) diff --git a/event/engins/epoll/fd_event.cpp b/event/engins/epoll/fd_event.cpp index 8dfb096..e37c03c 100644 --- a/event/engins/epoll/fd_event.cpp +++ b/event/engins/epoll/fd_event.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "fd_event.h" #include "loop.h" @@ -8,173 +9,28 @@ namespace tbox { namespace event { -namespace { -short EpollEventsToLocal(short epoll_events) -{ - short ret = 0; - if ((epoll_events & EPOLLIN) || (epoll_events & EPOLLPRI)) - ret |= FdEvent::kReadEvent; - if (epoll_events & EPOLLOUT) - ret |= FdEvent::kWriteEvent; - - return ret; -} - -short LocalEventsToEpoll(short local_events) -{ - short ret = 0; - if (local_events & FdEvent::kWriteEvent) - ret |= EPOLLOUT; - - if (local_events & FdEvent::kReadEvent) - ret |= EPOLLIN; - - return ret; -} - -} - -class EpollFdEventImpl -{ - public: - explicit EpollFdEventImpl(EpollLoop *wp_loop) - : wp_loop_(wp_loop) - { - memset(&ev_, 0, sizeof(ev_)); - } - - virtual ~EpollFdEventImpl() - { - disable(); - } - - bool initialize(int fd, short events) - { - disable(); - - fd_ = fd; - memset(&ev_, 0, sizeof(ev_)); - ev_.data.ptr = static_cast(this); - ev_.events = LocalEventsToEpoll(events); - - is_inited_ = true; - return true; - } - - inline int setCallback(const FdEvent::CallbackFunc &cb) - { - cb_index_ ++; - callbacks_.push_back(std::make_pair(cb_index_, cb)); - return cb_index_; - } - - inline bool isEnabled() const - { - if (!is_inited_) - return false; - - return is_enabled_; - } - - bool enable() - { - if (!is_inited_) - return false; - - if (isEnabled()) - return true; - - int ret = epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_, &ev_); - if (ret != 0) - return false; - - is_enabled_ = true; - return true; - } - - bool disable() - { - if (!is_inited_) - return false; - - if (!isEnabled()) - return true; - - epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_, NULL); - - is_enabled_ = false; - return true; - } - - inline void ref() { ref_count_ ++; } - inline bool noref() { return ref_count_ <= 0; } - void unref(int cb_index) - { - -- ref_count_; - using Element = std::pair; - auto is_equal_to_cb_index = [cb_index](const Element &e) -> bool - { - return e.first == cb_index; - }; - - auto result_it = std::find_if(callbacks_.begin(), callbacks_.end(), is_equal_to_cb_index); - if (result_it != callbacks_.end()) - callbacks_.erase(result_it); - } - - inline uint32_t getEvents() const - { - return EpollEventsToLocal(ev_.events); - } - - public: - static void OnEventCallback(int fd, uint32_t events, void *obj) - { - EpollFdEventImpl *self = static_cast(obj); - self->onEvent(events); - } - - protected: - void onEvent(uint32_t events) - { - short local_events = EpollEventsToLocal(events); - for (const auto &it : callbacks_) { - if (it.second) - it.second(local_events); - } - } - - private: - EpollLoop *wp_loop_; - bool is_inited_{ false }; - bool is_enabled_{ false }; - - std::vector > callbacks_; - - int fd_ { -1 }; - struct epoll_event ev_; - - int ref_count_{ 0 }; - int cb_index_{ 0 }; +//! 同一个fd共享的数据 +struct EpollFdSharedData { + int ref = 0; //! 引用计数 + struct epoll_event ev; + std::set read_events; + std::set write_events; }; EpollFdEvent::EpollFdEvent(EpollLoop *wp_loop) : - wp_loop_(wp_loop), - is_stop_after_trigger_(false), - cb_level_(0) -{ -} + wp_loop_(wp_loop) +{ } EpollFdEvent::~EpollFdEvent() { assert(cb_level_ == 0); - if (impl_ != nullptr) { - impl_->unref(cb_index_); - if (impl_->noref()) { - wp_loop_->unregisterFdevent(fd_); - delete impl_; - impl_ = nullptr; - } + + disable(); + + --d_->ref; + if (d_->ref == 0) { + wp_loop_->removeFdSharedData(fd_); + delete d_; } } @@ -182,99 +38,97 @@ bool EpollFdEvent::initialize(int fd, short events, Mode mode) { if (isEnabled()) return false; + fd_ = fd; events_ = events; if (mode == FdEvent::Mode::kOneshot) is_stop_after_trigger_ = true; - impl_ = wp_loop_->queryFdevent(fd_); - if (impl_ == nullptr) { - impl_ = new EpollFdEventImpl(wp_loop_); - assert(impl_ != nullptr); - wp_loop_->registerFdEvent(fd, impl_); - } - - impl_->ref(); - cb_index_ = impl_->setCallback( - [this](short events) { - if (events & events_) - onEvent(events); - }); + d_ = wp_loop_->queryFdSharedData(fd_); + if (d_ == nullptr) { + d_ = new EpollFdSharedData; + assert(d_ != nullptr); - return true; -} - -void EpollFdEvent::setCallback(const CallbackFunc &cb) -{ - cb_ = cb; -} + memset(&d_->ev, 0, sizeof(d_->ev)); + d_->ev.data.ptr = static_cast(d_); -bool EpollFdEvent::isEnabled() const -{ - if (nullptr == impl_) - return false; - - if (!impl_->isEnabled()) - return false; + wp_loop_->addFdSharedData(fd_, d_); + } - auto event_bit = impl_->getEvents() & events_; - return event_bit != 0; //!< means impl and this obj both were enabled + ++d_->ref; + return true; } bool EpollFdEvent::enable() { - if (impl_ == nullptr) + if (d_ == nullptr) return false; - uint32_t new_events = 0; - if (impl_->isEnabled()) { - uint32_t events = impl_->getEvents() & events_; - if (events == events_) - return true; + if (is_enabled_) + return true; - impl_->disable(); - new_events = impl_->getEvents() | events_; - } else { - new_events = events_; - } + if (events_ & kReadEvent) + d_->read_events.insert(this); + + if (events_ & kWriteEvent) + d_->write_events.insert(this); - impl_->initialize(fd_, new_events); + reloadEpoll(); - return impl_->enable(); + is_enabled_ = true; + return true; } bool EpollFdEvent::disable() { - if (nullptr == impl_) + if (d_ == nullptr || !is_enabled_) return true; - if (!impl_->isEnabled()) - return true; + if (events_ & kReadEvent) + d_->read_events.erase(this); - uint32_t events = impl_->getEvents() & events_; - if (events == 0) - return true; + if (events_ & kWriteEvent) + d_->write_events.erase(this); - impl_->disable(); - uint32_t new_events = impl_->getEvents() ^ events_; - if (new_events == 0) - return true; + reloadEpoll(); - impl_->initialize(fd_, new_events); - impl_->enable(); + is_enabled_ = false; return true; } -void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj) +Loop* EpollFdEvent::getLoop() const { - EpollFdEventImpl::OnEventCallback(fd, events, obj); + return wp_loop_; } -Loop* EpollFdEvent::getLoop() const +//! 重新加载fd对应的epoll +void EpollFdEvent::reloadEpoll() { - return wp_loop_; + epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_DEL, fd_, NULL); + + d_->ev.events = 0; + if (!d_->write_events.empty()) + d_->ev.events |= EPOLLOUT; + if (!d_->read_events.empty()) + d_->ev.events |= EPOLLIN; + + epoll_ctl(wp_loop_->epollFd(), EPOLL_CTL_ADD, fd_, &d_->ev); } +void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj) +{ + EpollFdSharedData *d = static_cast(obj); + + if (events & EPOLLIN) { + for (EpollFdEvent *event : d->read_events) + event->onEvent(kReadEvent); + } + + if (events & EPOLLOUT) { + for (EpollFdEvent *event : d->write_events) + event->onEvent(kWriteEvent); + } +} void EpollFdEvent::onEvent(short events) { @@ -292,5 +146,6 @@ void EpollFdEvent::onEvent(short events) wp_loop_->endEventProcess(); } + } } diff --git a/event/engins/epoll/fd_event.h b/event/engins/epoll/fd_event.h index b0507f0..e45fc51 100644 --- a/event/engins/epoll/fd_event.h +++ b/event/engins/epoll/fd_event.h @@ -9,40 +9,42 @@ namespace tbox { namespace event { class EpollLoop; -class EpollFdEventImpl; +class EpollFdSharedData; class EpollFdEvent : public FdEvent { public: explicit EpollFdEvent(EpollLoop *wp_loop); - virtual ~EpollFdEvent(); + ~EpollFdEvent() override; public: - virtual bool initialize(int fd, short events, Mode mode); - virtual void setCallback(const CallbackFunc &cb); + bool initialize(int fd, short events, Mode mode) override; + void setCallback(const CallbackFunc &cb) override { cb_ = cb; } - virtual bool isEnabled() const; - virtual bool enable(); - virtual bool disable(); + bool isEnabled() const override{ return is_enabled_; } + bool enable() override; + bool disable() override; - virtual Loop* getLoop() const; + Loop* getLoop() const override; public: static void OnEventCallback(int fd, uint32_t events, void *obj); protected: + void reloadEpoll(); void onEvent(short events); private: EpollLoop *wp_loop_; - bool is_stop_after_trigger_ { false }; - CallbackFunc cb_; - int cb_level_{ 0 }; - int cb_index_{ -1 }; + bool is_stop_after_trigger_ = false; + + int fd_ = -1; + uint32_t events_ = 0; + bool is_enabled_ = false; - int fd_ { -1 }; - uint32_t events_; + CallbackFunc cb_; + EpollFdSharedData *d_ = nullptr; - EpollFdEventImpl *impl_{ nullptr }; + int cb_level_ = 0; }; } diff --git a/event/engins/epoll/loop.cpp b/event/engins/epoll/loop.cpp index caa61fb..1e01a4e 100644 --- a/event/engins/epoll/loop.cpp +++ b/event/engins/epoll/loop.cpp @@ -192,6 +192,25 @@ void EpollLoop::deleteTimer(const cabinet::Token& token) run([timer] { delete timer; }); //! Delete later, avoid delete itself } +void EpollLoop::addFdSharedData(int fd, EpollFdSharedData *fd_event) +{ + fd_data_map_.insert(std::make_pair(fd, fd_event)); +} + +void EpollLoop::removeFdSharedData(int fd) +{ + fd_data_map_.erase(fd); +} + +EpollFdSharedData* EpollLoop::queryFdSharedData(int fd) const +{ + auto it = fd_data_map_.find(fd); + if (it != fd_data_map_.end()) + return it->second; + return nullptr; +} + + FdEvent* EpollLoop::newFdEvent() { return new EpollFdEvent(this); diff --git a/event/engins/epoll/loop.h b/event/engins/epoll/loop.h index c1c1034..5b5d146 100644 --- a/event/engins/epoll/loop.h +++ b/event/engins/epoll/loop.h @@ -15,7 +15,7 @@ namespace tbox { namespace event { -class EpollFdEventImpl; +struct EpollFdSharedData; class EpollLoop : public CommonLoop { public: @@ -37,20 +37,9 @@ class EpollLoop : public CommonLoop { cabinet::Token addTimer(uint64_t interval, uint64_t repeat, const TimerCallback &cb); void deleteTimer(const cabinet::Token &token); - inline void registerFdEvent(int fd, EpollFdEventImpl *fd_event) { - fd_event_map_.insert(std::make_pair(fd, fd_event)); - } - - inline void unregisterFdevent(int fd) { - fd_event_map_.erase(fd); - } - - inline EpollFdEventImpl *queryFdevent(int fd) const { - auto it = fd_event_map_.find(fd); - if (it != fd_event_map_.end()) - return it->second; - return nullptr; - } + void addFdSharedData(int fd, EpollFdSharedData *fd_data); + void removeFdSharedData(int fd); + EpollFdSharedData *queryFdSharedData(int fd) const; private: void onTimeExpired(); @@ -82,7 +71,7 @@ class EpollLoop : public CommonLoop { cabinet::Cabinet timer_cabinet_; std::vector timer_min_heap_; - std::unordered_map fd_event_map_; + std::unordered_map fd_data_map_; }; } -- Gitee From 214c87637042d9e96181d11a42b6e4b3b3680d73 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 17:12:08 +0800 Subject: [PATCH 18/25] =?UTF-8?q?=E5=B0=86EpollFdEvent=E4=B8=AD=E7=9A=84se?= =?UTF-8?q?t=E6=8D=A2=E6=88=90vector=EF=BC=8C=E5=9B=A0=E4=B8=BAset?= =?UTF-8?q?=E6=98=AF=E6=9C=89=E5=BA=8F=E7=9A=84=EF=BC=9B=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E4=BA=8B=E4=BB=B6=E8=A2=AB=E4=B8=A4=E4=B8=AAFdEvent?= =?UTF-8?q?=E7=9B=91=E5=90=AC=EF=BC=8C=E4=BD=8E=E5=9C=B0=E5=9D=80=E7=9A=84?= =?UTF-8?q?=E6=B0=B8=E8=BF=9C=E5=85=88=E8=A2=AB=E6=89=A7=E8=A1=8C=E3=80=82?= =?UTF-8?q?=E6=94=B9=E6=88=90vector=E5=90=8E=EF=BC=8C=E5=85=88enable?= =?UTF-8?q?=E7=9A=84=E5=85=88=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/epoll/fd_event.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/event/engins/epoll/fd_event.cpp b/event/engins/epoll/fd_event.cpp index e37c03c..b38e58a 100644 --- a/event/engins/epoll/fd_event.cpp +++ b/event/engins/epoll/fd_event.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include "fd_event.h" #include "loop.h" @@ -13,8 +13,8 @@ namespace event { struct EpollFdSharedData { int ref = 0; //! 引用计数 struct epoll_event ev; - std::set read_events; - std::set write_events; + std::vector read_events; + std::vector write_events; }; EpollFdEvent::EpollFdEvent(EpollLoop *wp_loop) : @@ -68,10 +68,10 @@ bool EpollFdEvent::enable() return true; if (events_ & kReadEvent) - d_->read_events.insert(this); + d_->read_events.push_back(this); if (events_ & kWriteEvent) - d_->write_events.insert(this); + d_->write_events.push_back(this); reloadEpoll(); @@ -84,11 +84,15 @@ bool EpollFdEvent::disable() if (d_ == nullptr || !is_enabled_) return true; - if (events_ & kReadEvent) - d_->read_events.erase(this); + if (events_ & kReadEvent) { + auto iter = std::find(d_->read_events.begin(), d_->read_events.end(), this); + d_->read_events.erase(iter); + } - if (events_ & kWriteEvent) - d_->write_events.erase(this); + if (events_ & kWriteEvent) { + auto iter = std::find(d_->write_events.begin(), d_->write_events.end(), this); + d_->write_events.erase(iter); + } reloadEpoll(); -- Gitee From e39232552210c8d26181c2fe4425658d2e61b653 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 17:51:47 +0800 Subject: [PATCH 19/25] =?UTF-8?q?=E6=B7=BB=E5=8A=A0SignalEvent=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/Makefile | 1 + event/signal_event_test.cpp | 117 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 event/signal_event_test.cpp diff --git a/event/Makefile b/event/Makefile index 655f757..0eced0e 100644 --- a/event/Makefile +++ b/event/Makefile @@ -50,6 +50,7 @@ TEST_CPP_SRC_FILES = \ common_loop_test.cpp \ fd_event_test.cpp \ timer_event_test.cpp \ + signal_event_test.cpp \ CXXFLAGS := -DLOG_MODULE_ID='"tbox_event"' $(CXXFLAGS) diff --git a/event/signal_event_test.cpp b/event/signal_event_test.cpp new file mode 100644 index 0000000..4c620f6 --- /dev/null +++ b/event/signal_event_test.cpp @@ -0,0 +1,117 @@ +#include +#include + +#include "loop.h" +#include "signal_event.h" +#include "timer_event.h" + +using namespace std; +using namespace tbox::event; + +const int kAcceptableError = 10; + +TEST(SignalEvent, Oneshot) +{ + auto engins = Loop::Engines(); + for (auto e : engins) { + cout << "engin: " << e << endl; + auto sp_loop = Loop::New(e); + auto signal_event = sp_loop->newSignalEvent(); + EXPECT_TRUE(signal_event->initialize(SIGUSR1, Event::Mode::kOneshot)); + EXPECT_TRUE(signal_event->enable()); + + int run_time = 0; + signal_event->setCallback([&]() { ++run_time; }); + + sp_loop->run([] + { + pid_t pid = getpid(); + kill(pid, SIGUSR1); + } + ); + sp_loop->exitLoop(std::chrono::milliseconds(100)); + sp_loop->runLoop(); + + EXPECT_EQ(run_time, 1); + + delete signal_event; + delete sp_loop; + } +} + +TEST(SignalEvent, Persist) +{ + auto engins = Loop::Engines(); + for (auto e : engins) { + cout << "engin: " << e << endl; + auto sp_loop = Loop::New(e); + auto signal_event = sp_loop->newSignalEvent(); + EXPECT_TRUE(signal_event->initialize(SIGUSR1, Event::Mode::kPersist)); + EXPECT_TRUE(signal_event->enable()); + + auto timer_event = sp_loop->newTimerEvent(); + EXPECT_TRUE(timer_event->initialize(chrono::milliseconds(10), Event::Mode::kPersist)); + EXPECT_TRUE(timer_event->enable()); + int count = 0; + timer_event->setCallback([&] + { + ++count; + if (count <= 5) { + pid_t pid = getpid(); + kill(pid, SIGUSR1); + } + } + ); + + int run_time = 0; + signal_event->setCallback([&]() { ++run_time; }); + + sp_loop->exitLoop(std::chrono::milliseconds(100)); + sp_loop->runLoop(); + + EXPECT_EQ(run_time, 5); + + delete timer_event; + delete signal_event; + delete sp_loop; + } +} + +TEST(SignalEvent, IntAndTermSignal) +{ + auto engins = Loop::Engines(); + for (auto e : engins) { + cout << "engin: " << e << endl; + auto sp_loop = Loop::New(e); + auto int_signal_event = sp_loop->newSignalEvent(); + EXPECT_TRUE(int_signal_event->initialize(SIGUSR1, Event::Mode::kOneshot)); + EXPECT_TRUE(int_signal_event->enable()); + + auto term_signal_event = sp_loop->newSignalEvent(); + EXPECT_TRUE(term_signal_event->initialize(SIGUSR2, Event::Mode::kOneshot)); + EXPECT_TRUE(term_signal_event->enable()); + + int int_run_time = 0; + int_signal_event->setCallback([&]() { ++int_run_time; }); + int term_run_time = 0; + term_signal_event->setCallback([&]() { ++term_run_time; }); + + sp_loop->run([] + { + pid_t pid = getpid(); + kill(pid, SIGUSR1); + kill(pid, SIGUSR2); + } + ); + sp_loop->exitLoop(std::chrono::milliseconds(100)); + sp_loop->runLoop(); + + EXPECT_EQ(int_run_time, 1); + EXPECT_EQ(term_run_time, 1); + + delete int_signal_event; + delete term_signal_event; + delete sp_loop; + } +} + -- Gitee From a19fd7a164813e9862b3daab3c20f50ba56dfa85 Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 17:57:55 +0800 Subject: [PATCH 20/25] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/signal_event_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/event/signal_event_test.cpp b/event/signal_event_test.cpp index 4c620f6..e9e233f 100644 --- a/event/signal_event_test.cpp +++ b/event/signal_event_test.cpp @@ -17,7 +17,7 @@ TEST(SignalEvent, Oneshot) cout << "engin: " << e << endl; auto sp_loop = Loop::New(e); auto signal_event = sp_loop->newSignalEvent(); - EXPECT_TRUE(signal_event->initialize(SIGUSR1, Event::Mode::kOneshot)); + EXPECT_TRUE(signal_event->initialize(SIGINT, Event::Mode::kOneshot)); EXPECT_TRUE(signal_event->enable()); int run_time = 0; @@ -26,7 +26,7 @@ TEST(SignalEvent, Oneshot) sp_loop->run([] { pid_t pid = getpid(); - kill(pid, SIGUSR1); + kill(pid, SIGINT); } ); sp_loop->exitLoop(std::chrono::milliseconds(100)); @@ -39,14 +39,14 @@ TEST(SignalEvent, Oneshot) } } -TEST(SignalEvent, Persist) +TEST(SignalEvent, PersistWithTimerEvent) { auto engins = Loop::Engines(); for (auto e : engins) { cout << "engin: " << e << endl; auto sp_loop = Loop::New(e); auto signal_event = sp_loop->newSignalEvent(); - EXPECT_TRUE(signal_event->initialize(SIGUSR1, Event::Mode::kPersist)); + EXPECT_TRUE(signal_event->initialize(SIGINT, Event::Mode::kPersist)); EXPECT_TRUE(signal_event->enable()); auto timer_event = sp_loop->newTimerEvent(); @@ -58,7 +58,7 @@ TEST(SignalEvent, Persist) ++count; if (count <= 5) { pid_t pid = getpid(); - kill(pid, SIGUSR1); + kill(pid, SIGINT); } } ); @@ -84,11 +84,11 @@ TEST(SignalEvent, IntAndTermSignal) cout << "engin: " << e << endl; auto sp_loop = Loop::New(e); auto int_signal_event = sp_loop->newSignalEvent(); - EXPECT_TRUE(int_signal_event->initialize(SIGUSR1, Event::Mode::kOneshot)); + EXPECT_TRUE(int_signal_event->initialize(SIGINT, Event::Mode::kOneshot)); EXPECT_TRUE(int_signal_event->enable()); auto term_signal_event = sp_loop->newSignalEvent(); - EXPECT_TRUE(term_signal_event->initialize(SIGUSR2, Event::Mode::kOneshot)); + EXPECT_TRUE(term_signal_event->initialize(SIGTERM, Event::Mode::kOneshot)); EXPECT_TRUE(term_signal_event->enable()); int int_run_time = 0; @@ -99,8 +99,8 @@ TEST(SignalEvent, IntAndTermSignal) sp_loop->run([] { pid_t pid = getpid(); - kill(pid, SIGUSR1); - kill(pid, SIGUSR2); + kill(pid, SIGINT); + kill(pid, SIGTERM); } ); sp_loop->exitLoop(std::chrono::milliseconds(100)); -- Gitee From 5daf5701c77d0614959ff077ecf1a151c539921c Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 23:17:47 +0800 Subject: [PATCH 21/25] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/epoll/signal_event.cpp | 31 ++++++++++++++++------------- event/engins/epoll/signal_event.h | 10 +++++++--- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/event/engins/epoll/signal_event.cpp b/event/engins/epoll/signal_event.cpp index 8aa9b30..2be51f2 100644 --- a/event/engins/epoll/signal_event.cpp +++ b/event/engins/epoll/signal_event.cpp @@ -1,13 +1,13 @@ #include #include #include -#include #include #include #include "signal_event.h" #include +#include #include "loop.h" #include "fd_event.h" @@ -15,9 +15,13 @@ namespace tbox { namespace event { EpollSignalEvent::EpollSignalEvent(EpollLoop *wp_loop) : - wp_loop_(wp_loop) - ,signal_fd_event_(new EpollFdEvent(wp_loop)) -{ } + wp_loop_(wp_loop), + signal_fd_event_(new EpollFdEvent(wp_loop)) +{ + sigemptyset(&sig_mask_); + signal_fd_ = signalfd(-1, &sig_mask_, SFD_NONBLOCK | SFD_CLOEXEC); + assert(signal_fd_ >= 0); +} EpollSignalEvent::~EpollSignalEvent() { @@ -25,27 +29,20 @@ EpollSignalEvent::~EpollSignalEvent() disable(); CHECK_DELETE_RESET_OBJ(signal_fd_event_); + CHECK_CLOSE_RESET_FD(signal_fd_); } bool EpollSignalEvent::initialize(int signum, Mode mode) { disable(); - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, signum); - if (sigprocmask(SIG_BLOCK, &mask, 0) == -1) - return false; - - signal_fd_ = signalfd(-1, &mask, 0); - if (signal_fd_ == -1) - return false; - if (!signal_fd_event_->initialize(signal_fd_, FdEvent::kReadEvent, mode)) return false; signal_fd_event_->setCallback(std::bind(&EpollSignalEvent::onEvent, this, std::placeholders::_1)); + sigaddset(&sig_mask_, signum); + if (mode == Mode::kOneshot) is_stop_after_trigger_ = true; @@ -77,6 +74,9 @@ bool EpollSignalEvent::enable() if (!signal_fd_event_->enable()) return false; + signalfd(signal_fd_, &sig_mask_, 0); + sigprocmask(SIG_BLOCK, &sig_mask_, 0); + return true; } @@ -88,6 +88,9 @@ bool EpollSignalEvent::disable() if (!isEnabled()) return true; + sigprocmask(SIG_UNBLOCK, &sig_mask_, 0); + signalfd(signal_fd_, &sig_mask_, 0); + if (!signal_fd_event_->disable()) return false; diff --git a/event/engins/epoll/signal_event.h b/event/engins/epoll/signal_event.h index 4792dc8..1538c27 100644 --- a/event/engins/epoll/signal_event.h +++ b/event/engins/epoll/signal_event.h @@ -1,6 +1,7 @@ #ifndef TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 #define TBOX_EVENT_EPOLL_SINGAL_EVENT_H_20220110 +#include #include "../../signal_event.h" struct epoll_event; @@ -31,13 +32,16 @@ class EpollSignalEvent : public SignalEvent { private: EpollLoop *wp_loop_{ nullptr }; - EpollFdEvent *signal_fd_event_{ nullptr }; bool is_inited_{ false }; bool is_stop_after_trigger_{ false }; CallbackFunc cb_{ nullptr }; - int cb_level_{ 0 }; - int signal_fd_{ -1 }; + + int signal_fd_ = -1; + sigset_t sig_mask_; + EpollFdEvent *signal_fd_event_ = nullptr; + + int cb_level_ = 0; }; } -- Gitee From 59d116659e4b6afe9f32af1aabe4f0942f8f6c6a Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 23:22:56 +0800 Subject: [PATCH 22/25] =?UTF-8?q?=E4=BC=98=E5=8C=96EpollSignalEvent?= =?UTF-8?q?=EF=BC=8C=E5=8E=BB=E9=99=A4=E9=87=8C=E9=9D=A2EpollFdEvent?= =?UTF-8?q?=E7=9A=84=E6=8C=87=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/epoll/signal_event.cpp | 14 ++++++-------- event/engins/epoll/signal_event.h | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/event/engins/epoll/signal_event.cpp b/event/engins/epoll/signal_event.cpp index 2be51f2..beb80fc 100644 --- a/event/engins/epoll/signal_event.cpp +++ b/event/engins/epoll/signal_event.cpp @@ -9,14 +9,13 @@ #include #include #include "loop.h" -#include "fd_event.h" namespace tbox { namespace event { EpollSignalEvent::EpollSignalEvent(EpollLoop *wp_loop) : wp_loop_(wp_loop), - signal_fd_event_(new EpollFdEvent(wp_loop)) + signal_fd_event_(wp_loop) { sigemptyset(&sig_mask_); signal_fd_ = signalfd(-1, &sig_mask_, SFD_NONBLOCK | SFD_CLOEXEC); @@ -28,7 +27,6 @@ EpollSignalEvent::~EpollSignalEvent() assert(cb_level_ == 0); disable(); - CHECK_DELETE_RESET_OBJ(signal_fd_event_); CHECK_CLOSE_RESET_FD(signal_fd_); } @@ -36,10 +34,10 @@ bool EpollSignalEvent::initialize(int signum, Mode mode) { disable(); - if (!signal_fd_event_->initialize(signal_fd_, FdEvent::kReadEvent, mode)) + if (!signal_fd_event_.initialize(signal_fd_, FdEvent::kReadEvent, mode)) return false; - signal_fd_event_->setCallback(std::bind(&EpollSignalEvent::onEvent, this, std::placeholders::_1)); + signal_fd_event_.setCallback(std::bind(&EpollSignalEvent::onEvent, this, std::placeholders::_1)); sigaddset(&sig_mask_, signum); @@ -60,7 +58,7 @@ bool EpollSignalEvent::isEnabled() const if (!is_inited_) return false; - return signal_fd_event_->isEnabled(); + return signal_fd_event_.isEnabled(); } bool EpollSignalEvent::enable() @@ -71,7 +69,7 @@ bool EpollSignalEvent::enable() if (isEnabled()) return true; - if (!signal_fd_event_->enable()) + if (!signal_fd_event_.enable()) return false; signalfd(signal_fd_, &sig_mask_, 0); @@ -91,7 +89,7 @@ bool EpollSignalEvent::disable() sigprocmask(SIG_UNBLOCK, &sig_mask_, 0); signalfd(signal_fd_, &sig_mask_, 0); - if (!signal_fd_event_->disable()) + if (!signal_fd_event_.disable()) return false; return true; diff --git a/event/engins/epoll/signal_event.h b/event/engins/epoll/signal_event.h index 1538c27..61d8a1f 100644 --- a/event/engins/epoll/signal_event.h +++ b/event/engins/epoll/signal_event.h @@ -3,6 +3,7 @@ #include #include "../../signal_event.h" +#include "fd_event.h" struct epoll_event; @@ -39,7 +40,7 @@ class EpollSignalEvent : public SignalEvent { int signal_fd_ = -1; sigset_t sig_mask_; - EpollFdEvent *signal_fd_event_ = nullptr; + EpollFdEvent signal_fd_event_; int cb_level_ = 0; }; -- Gitee From d7756830b83243382718d27c5052c5ae425f435d Mon Sep 17 00:00:00 2001 From: Hevake Date: Sun, 27 Feb 2022 23:40:44 +0800 Subject: [PATCH 23/25] =?UTF-8?q?=E4=BC=98=E5=8C=96SignalEvent=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/signal_event_test.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/event/signal_event_test.cpp b/event/signal_event_test.cpp index e9e233f..a38db6c 100644 --- a/event/signal_event_test.cpp +++ b/event/signal_event_test.cpp @@ -25,8 +25,7 @@ TEST(SignalEvent, Oneshot) sp_loop->run([] { - pid_t pid = getpid(); - kill(pid, SIGINT); + raise(SIGINT); } ); sp_loop->exitLoop(std::chrono::milliseconds(100)); @@ -57,8 +56,7 @@ TEST(SignalEvent, PersistWithTimerEvent) { ++count; if (count <= 5) { - pid_t pid = getpid(); - kill(pid, SIGINT); + raise(SIGINT); } } ); @@ -98,9 +96,8 @@ TEST(SignalEvent, IntAndTermSignal) sp_loop->run([] { - pid_t pid = getpid(); - kill(pid, SIGINT); - kill(pid, SIGTERM); + raise(SIGINT); + raise(SIGTERM); } ); sp_loop->exitLoop(std::chrono::milliseconds(100)); -- Gitee From ae02688b6feb76067440fc6a3605a1da03b2796b Mon Sep 17 00:00:00 2001 From: Hevake Date: Mon, 28 Feb 2022 08:19:25 +0800 Subject: [PATCH 24/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9main=EF=BC=8C=E5=9C=A8m?= =?UTF-8?q?ain=E4=B8=AD=E6=91=92=E5=BC=83=E4=BA=86SignalEvent=E7=9A=84?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=EF=BC=8C=E7=9B=B4=E6=8E=A5=E9=87=87=E7=94=A8?= =?UTF-8?q?signal()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Makefile | 2 +- main/main.cpp | 35 +++++++++------------------ main/{error_handle.cpp => signal.cpp} | 11 +++++++++ 3 files changed, 24 insertions(+), 24 deletions(-) rename main/{error_handle.cpp => signal.cpp} (83%) diff --git a/main/Makefile b/main/Makefile index 9dd93b6..c88f3a2 100644 --- a/main/Makefile +++ b/main/Makefile @@ -13,7 +13,7 @@ CPP_SRC_FILES = \ apps_imp.cpp \ context_imp.cpp \ main.cpp \ - error_handle.cpp \ + signal.cpp \ misc.cpp \ args.cpp \ diff --git a/main/main.cpp b/main/main.cpp index 9189432..6fe8559 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -27,6 +26,7 @@ extern void RegisterApps(Apps &apps); //! 由用户去实现 extern void Run(ContextImp &ctx, AppsImp &apps, int loop_exit_wait); std::function error_exit_func; //!< 出错异常退出前要做的事件 +std::function normal_stop_func; //!< 正常退出前要做的事件 int Main(int argc, char **argv) { @@ -111,28 +111,19 @@ int Main(int argc, char **argv) void Run(ContextImp &ctx, AppsImp &apps, int loop_exit_wait) { auto feeddog_timer = ctx.loop()->newTimerEvent(); - auto sig_int_event = ctx.loop()->newSignalEvent(); - auto sig_term_event = ctx.loop()->newSignalEvent(); //! 预定在离开时自动释放对象,确保无内存泄漏 - SetScopeExitAction( - [feeddog_timer, sig_int_event, sig_term_event] { - delete sig_term_event; - delete sig_int_event; - delete feeddog_timer; - } - ); - - sig_int_event->initialize(SIGINT, event::Event::Mode::kOneshot); - sig_term_event->initialize(SIGTERM, event::Event::Mode::kOneshot); - auto normal_stop_func = [&] { - LogInfo("Got stop signal"); - apps.stop(); - ctx.stop(); - ctx.loop()->exitLoop(std::chrono::seconds(loop_exit_wait)); - LogInfo("Loop will exit after %d sec", loop_exit_wait); + SetScopeExitAction([feeddog_timer] { delete feeddog_timer; }); + + normal_stop_func = [&] { + ctx.loop()->runInLoop([&] { + LogInfo("Got stop signal"); + apps.stop(); + ctx.stop(); + ctx.loop()->exitLoop(std::chrono::seconds(loop_exit_wait)); + LogInfo("Loop will exit after %d sec", loop_exit_wait); + } + ); }; - sig_int_event->setCallback(normal_stop_func); - sig_term_event->setCallback(normal_stop_func); //! 创建喂狗定时器 feeddog_timer->initialize(std::chrono::seconds(2), event::Event::Mode::kPersist); @@ -143,8 +134,6 @@ void Run(ContextImp &ctx, AppsImp &apps, int loop_exit_wait) util::ThreadWDog::Register("main", 3); feeddog_timer->enable(); - sig_int_event->enable(); - sig_term_event->enable(); LogInfo("Start!"); diff --git a/main/error_handle.cpp b/main/signal.cpp similarity index 83% rename from main/error_handle.cpp rename to main/signal.cpp index ba83d31..5de2369 100644 --- a/main/error_handle.cpp +++ b/main/signal.cpp @@ -10,9 +10,18 @@ namespace tbox::main { extern std::function error_exit_func; //!< 出错异常退出前要做的事件 +extern std::function normal_stop_func; //!< 正常退出前要做的事件 namespace { +void OnStopSignal(int) +{ + if (normal_stop_func) + normal_stop_func(); + else + exit(0); +} + //! 打印调用栈 void PrintCallStack() { @@ -59,6 +68,8 @@ void RegisterSignals() signal(SIGABRT, OnErrorSignal); signal(SIGBUS, OnErrorSignal); signal(SIGPIPE, OnWarnSignal); + signal(SIGINT, OnStopSignal); + signal(SIGTERM, OnStopSignal); } } -- Gitee From fba0149e08272d6769abd573c9a5cd88db312ce7 Mon Sep 17 00:00:00 2001 From: Hevake Date: Mon, 28 Feb 2022 08:27:12 +0800 Subject: [PATCH 25/25] =?UTF-8?q?=E5=9C=A8EpollLoop::newSignalEvent()?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=8F=90=E7=A4=BA=EF=BC=8C=E8=AD=A6?= =?UTF-8?q?=E5=91=8A=E5=85=B6=E6=85=8E=E7=94=A8EpollSignalEvent=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- event/engins/epoll/loop.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/event/engins/epoll/loop.cpp b/event/engins/epoll/loop.cpp index 1e01a4e..3bfcefc 100644 --- a/event/engins/epoll/loop.cpp +++ b/event/engins/epoll/loop.cpp @@ -1,21 +1,18 @@ #include #include -#include #include -#include #include #include -#include -#include #include "loop.h" #include "timer_event.h" #include "fd_event.h" #include "signal_event.h" -#include "tbox/base/defines.h" +#include +#include namespace tbox { namespace event { @@ -223,6 +220,7 @@ TimerEvent* EpollLoop::newTimerEvent() SignalEvent* EpollLoop::newSignalEvent() { + LogWarn("EpollSignalEvent is not stable in multithread"); return new EpollSignalEvent(this); } -- Gitee