Skip to content

Commit 6b3db4a

Browse files
committed
merge:1.8.7
2 parents 6f935c9 + cf16ba1 commit 6b3db4a

File tree

9 files changed

+203
-50
lines changed

9 files changed

+203
-50
lines changed

examples/event/09_named_pipe/Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# .============.
3+
# // M A K E / \
4+
# // C++ DEV / \
5+
# // E A S Y / \/ \
6+
# ++ ----------. \/\ .
7+
# \\ \ \ /\ /
8+
# \\ \ \ /
9+
# \\ \ \ /
10+
# -============'
11+
#
12+
# Copyright (c) 2024 Hevake and contributors, all rights reserved.
13+
#
14+
# This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
# Use of this source code is governed by MIT license that can be found
16+
# in the LICENSE file in the root of the source tree. All contributing
17+
# project authors may be found in the CONTRIBUTORS.md file in the root
18+
# of the source tree.
19+
#
20+
21+
PROJECT := example/event/09_named_pipe
22+
EXE_NAME := 09_named_pipe
23+
24+
CPP_SRC_FILES := main.cpp
25+
26+
CXXFLAGS := -DLOG_MODULE_ID='"$(EXE_NAME)"' $(CXXFLAGS)
27+
LDFLAGS += \
28+
-ltbox_event \
29+
-ltbox_base \
30+
-ldl
31+
32+
include ${TOP_DIR}/tools/exe_common.mk

examples/event/09_named_pipe/main.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* .============.
3+
* // M A K E / \
4+
* // C++ DEV / \
5+
* // E A S Y / \/ \
6+
* ++ ----------. \/\ .
7+
* \\ \ \ /\ /
8+
* \\ \ \ /
9+
* \\ \ \ /
10+
* -============'
11+
*
12+
* Copyright (c) 2024 Hevake and contributors, all rights reserved.
13+
*
14+
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
* Use of this source code is governed by MIT license that can be found
16+
* in the LICENSE file in the root of the source tree. All contributing
17+
* project authors may be found in the CONTRIBUTORS.md file in the root
18+
* of the source tree.
19+
*/
20+
/**
21+
* 本示例,有名管道的读取
22+
*/
23+
24+
#include <unistd.h>
25+
#include <sys/types.h>
26+
#include <sys/stat.h>
27+
#include <fcntl.h>
28+
29+
#include <iostream>
30+
#include <sstream>
31+
#include <cstring>
32+
33+
#include <tbox/base/log.h>
34+
#include <tbox/base/log_output.h>
35+
#include <tbox/event/loop.h>
36+
#include <tbox/event/fd_event.h>
37+
38+
using namespace std;
39+
using namespace tbox;
40+
using namespace tbox::event;
41+
42+
void PrintUsage(const char *process_name)
43+
{
44+
cout << "Usage:" << process_name << " your_pipefile" << endl;
45+
}
46+
47+
int main(int argc, char *argv[])
48+
{
49+
if (argc < 2) {
50+
PrintUsage(argv[0]);
51+
return 0;
52+
}
53+
54+
LogOutput_Enable();
55+
Loop* sp_loop = Loop::New();
56+
57+
const char* pipe_file = argv[1];
58+
int ret = mkfifo(pipe_file, 0666);
59+
if (ret != 0) {
60+
LogWarn("mkfifo() ret:%d, errno:%d", ret, errno);
61+
}
62+
int fd = open(pipe_file, O_RDONLY|O_NDELAY);
63+
64+
FdEvent* sp_fd_read = sp_loop->newFdEvent();
65+
sp_fd_read->initialize(fd, FdEvent::kReadEvent | FdEvent::kHupEvent, Event::Mode::kPersist); //! 可读与挂起事件一直有效
66+
sp_fd_read->enable();
67+
68+
sp_fd_read->setCallback(
69+
[&] (short event) {
70+
//! 当管道有输入的时候
71+
if (event & FdEvent::kReadEvent) {
72+
char input_buff[200];
73+
int rsize = read(fd, input_buff, sizeof(input_buff));
74+
if (rsize > 0) {
75+
input_buff[rsize - 1] = '\0';
76+
LogInfo("read[%d]:%s", rsize, input_buff);
77+
} else {
78+
LogInfo("read 0");
79+
}
80+
}
81+
82+
//! 当管道断开的时候
83+
if (event & FdEvent::kHupEvent) {
84+
LogNotice("hup");
85+
fd = open(pipe_file, O_RDONLY|O_NDELAY);
86+
sp_fd_read->initialize(fd, FdEvent::kReadEvent | FdEvent::kHupEvent, Event::Mode::kPersist);
87+
sp_fd_read->enable();
88+
}
89+
}
90+
);
91+
92+
sp_loop->runLoop(Loop::Mode::kForever);
93+
94+
delete sp_fd_read;
95+
delete sp_loop;
96+
97+
return 0;
98+
}

modules/event/engines/epoll/fd_event.cpp

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ bool EpollFdEvent::enable()
7070
return true;
7171

7272
if (events_ & kReadEvent)
73-
d_->read_events.push_back(this);
73+
++d_->read_event_num;
7474

7575
if (events_ & kWriteEvent)
76-
d_->write_events.push_back(this);
76+
++d_->write_event_num;
7777

7878
if (events_ & kExceptEvent)
79-
d_->exception_events.push_back(this);
79+
++d_->except_event_num;
80+
81+
d_->fd_events.push_back(this);
8082

8183
reloadEpoll();
8284

@@ -89,20 +91,17 @@ bool EpollFdEvent::disable()
8991
if (d_ == nullptr || !is_enabled_)
9092
return true;
9193

92-
if (events_ & kReadEvent) {
93-
auto iter = std::find(d_->read_events.begin(), d_->read_events.end(), this);
94-
d_->read_events.erase(iter);
95-
}
94+
if (events_ & kReadEvent)
95+
--d_->read_event_num;
9696

97-
if (events_ & kWriteEvent) {
98-
auto iter = std::find(d_->write_events.begin(), d_->write_events.end(), this);
99-
d_->write_events.erase(iter);
100-
}
97+
if (events_ & kWriteEvent)
98+
--d_->write_event_num;
10199

102-
if (events_ & kExceptEvent) {
103-
auto iter = std::find(d_->exception_events.begin(), d_->exception_events.end(), this);
104-
d_->exception_events.erase(iter);
105-
}
100+
if (events_ & kExceptEvent)
101+
--d_->except_event_num;
102+
103+
auto iter = std::find(d_->fd_events.begin(), d_->fd_events.end(), this);
104+
d_->fd_events.erase(iter);
106105

107106
reloadEpoll();
108107

@@ -121,12 +120,14 @@ void EpollFdEvent::reloadEpoll()
121120
uint32_t old_events = d_->ev.events;
122121
uint32_t new_events = 0;
123122

124-
if (!d_->write_events.empty())
123+
if (d_->write_event_num > 0)
125124
new_events |= EPOLLOUT;
126-
if (!d_->read_events.empty())
125+
126+
if (d_->read_event_num > 0)
127127
new_events |= EPOLLIN;
128-
if (!d_->exception_events.empty())
129-
new_events |= (EPOLLHUP | EPOLLERR);
128+
129+
if (d_->except_event_num > 0)
130+
new_events |= EPOLLERR;
130131

131132
d_->ev.events = new_events;
132133

@@ -141,45 +142,61 @@ void EpollFdEvent::reloadEpoll()
141142
}
142143
}
143144

144-
void EpollFdEvent::OnEventCallback(int fd, uint32_t events, void *obj)
145+
void EpollFdEvent::OnEventCallback(uint32_t events, void *obj)
145146
{
146147
EpollFdSharedData *d = static_cast<EpollFdSharedData*>(obj);
147148

149+
short tbox_events = 0;
148150
if (events & EPOLLIN) {
149151
events &= ~EPOLLIN;
150-
for (EpollFdEvent *event : d->read_events)
151-
event->onEvent(kReadEvent);
152+
tbox_events |= kReadEvent;
152153
}
153154

154155
if (events & EPOLLOUT) {
155156
events &= ~EPOLLOUT;
156-
for (EpollFdEvent *event : d->write_events)
157-
event->onEvent(kWriteEvent);
157+
tbox_events |= kWriteEvent;
158158
}
159159

160-
if (events & (EPOLLHUP | EPOLLERR)) {
161-
events &= ~(EPOLLHUP | EPOLLERR);
162-
for (EpollFdEvent *event : d->exception_events)
163-
event->onEvent(kExceptEvent);
160+
if (events & EPOLLERR) {
161+
events &= ~EPOLLERR;
162+
tbox_events |= kExceptEvent;
164163
}
165164

166-
if (events) {
167-
LogNotice("unhandle events:%08X, fd:%d", events, fd);
165+
if (events & EPOLLHUP) {
166+
events &= ~EPOLLHUP;
167+
tbox_events |= kHupEvent;
168168
}
169+
170+
//! 要先复制一份,因为在for中很可能会改动到d->fd_events,引起迭代器失效问题
171+
auto tmp = d->fd_events;
172+
for (auto event : tmp)
173+
event->onEvent(tbox_events);
174+
175+
if (events)
176+
LogWarn("unhandle events:%08X, fd:%d", events, d->fd);
169177
}
170178

171179
void EpollFdEvent::onEvent(short events)
172180
{
173-
if (is_stop_after_trigger_)
181+
/**
182+
* 由于EPOLLHUP会一直触发,所以无论事件有没有监听HupEvent,只要发生了EPOLLHUB事件,
183+
* 对应fd所有的事件都要强制disable()。否则会导致Loop空跑问题。
184+
*/
185+
if (events & kHupEvent)
174186
disable();
175187

176-
wp_loop_->beginEventProcess();
177-
if (cb_) {
178-
++cb_level_;
179-
cb_(events);
180-
--cb_level_;
188+
if (events_ & events) {
189+
if (is_stop_after_trigger_)
190+
disable();
191+
192+
wp_loop_->beginEventProcess();
193+
if (cb_) {
194+
++cb_level_;
195+
cb_(events);
196+
--cb_level_;
197+
}
198+
wp_loop_->endEventProcess(this);
181199
}
182-
wp_loop_->endEventProcess(this);
183200
}
184201

185202
}

modules/event/engines/epoll/fd_event.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class EpollFdEvent : public FdEvent {
4444
virtual Loop* getLoop() const override;
4545

4646
public:
47-
static void OnEventCallback(int fd, uint32_t events, void *obj);
47+
static void OnEventCallback(uint32_t events, void *obj);
4848

4949
protected:
5050
void reloadEpoll();

modules/event/engines/epoll/loop.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void EpollLoop::runLoop(Mode mode)
7676

7777
for (int i = 0; i < fds; ++i) {
7878
epoll_event &ev = events.at(i);
79-
EpollFdEvent::OnEventCallback(ev.data.fd, ev.events, ev.data.ptr);
79+
EpollFdEvent::OnEventCallback(ev.events, ev.data.ptr);
8080
}
8181

8282
//handleRunInLoopFunc();
@@ -108,6 +108,7 @@ EpollFdSharedData* EpollLoop::refFdSharedData(int fd)
108108
TBOX_ASSERT(fd_shared_data != nullptr);
109109

110110
::memset(&fd_shared_data->ev, 0, sizeof(fd_shared_data->ev));
111+
fd_shared_data->fd = fd;
111112
fd_shared_data->ev.data.ptr = static_cast<void *>(fd_shared_data);
112113

113114
fd_data_map_.insert(std::make_pair(fd, fd_shared_data));

modules/event/engines/epoll/types.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ class EpollFdEvent;
3030

3131
//! 同一个fd共享的数据
3232
struct EpollFdSharedData {
33-
int ref = 0; //! 引用计数
33+
int fd = 0; //!< 文件描述符
34+
int ref = 0; //!< 引用计数
3435
struct epoll_event ev;
35-
std::vector<EpollFdEvent*> read_events;
36-
std::vector<EpollFdEvent*> write_events;
37-
std::vector<EpollFdEvent*> exception_events;
36+
37+
int read_event_num = 0; //!< 监听可读事件的FdEvent个数
38+
int write_event_num = 0; //!< 监听可写事件的FdEvent个数
39+
int except_event_num = 0; //!< 监听异常事件的FdEvent个数
40+
41+
std::vector<EpollFdEvent*> fd_events;
3842
};
3943

4044
}

modules/event/fd_event.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ namespace event {
3030
class FdEvent : public Event {
3131
public:
3232
enum EventTypes {
33-
kReadEvent = 0x01,
34-
kWriteEvent = 0x02,
35-
kExceptEvent = 0x04,
33+
kReadEvent = 0x01, //!< 可读事件
34+
kWriteEvent = 0x02, //!< 可写事件
35+
kExceptEvent = 0x04, //!< 异常事件
36+
kHupEvent = 0x08, //!< 断开事件
3637
};
3738

3839
using Event::Event;

modules/event/fd_event_test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,23 +361,23 @@ TEST(FdEvent, Exception)
361361

362362
int run_time = 0;
363363

364-
EXPECT_TRUE(read_fd_event->initialize(read_fd, FdEvent::kReadEvent | FdEvent::kExceptEvent, Event::Mode::kPersist));
364+
EXPECT_TRUE(read_fd_event->initialize(read_fd, FdEvent::kReadEvent | FdEvent::kHupEvent, Event::Mode::kPersist));
365365
read_fd_event->setCallback([&](short events){
366366
if (events & FdEvent::kReadEvent) {
367367
char data[100] = { 0};
368368
ssize_t len = read(read_fd, data, sizeof(data));
369369
EXPECT_EQ(len, sizeof(int));
370370
}
371371

372-
if (events & FdEvent::kExceptEvent) {
372+
if (events & FdEvent::kHupEvent) {
373373
++run_time;
374374
loop->exitLoop();
375375
}
376376
});
377377

378378
read_fd_event->enable();
379379

380-
EXPECT_TRUE(write_fd_event->initialize(write_fd, FdEvent::kWriteEvent | FdEvent::kExceptEvent, Event::Mode::kPersist));
380+
EXPECT_TRUE(write_fd_event->initialize(write_fd, FdEvent::kWriteEvent, Event::Mode::kPersist));
381381
write_fd_event->setCallback([&](short events){
382382
if (events & FdEvent::kWriteEvent) {
383383
int data = 0;

version.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# TBOX版本号
22
TBOX_VERSION_MAJOR := 1
33
TBOX_VERSION_MINOR := 8
4-
TBOX_VERSION_REVISION := 6
4+
TBOX_VERSION_REVISION := 7

0 commit comments

Comments
 (0)