Skip to content

Commit bbfa547

Browse files
author
渡世白玉
committed
在类Unix系统下,用libev的事件循环代替qt自带的。
也就是对于处理socket的I/O复用,在linux下默认用epoll代替了poll, 在BSD和mac系统下用 kqueue代替了select
1 parent d45b1ca commit bbfa547

17 files changed

+983
-15
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ QtConcurrent : 负责处理发送过来的数据。(动态的线程数目。)
2525

2626
===========================
2727
Next:
28-
Qt的事件循环在win下是基于select的,在类unix下,如果有glib则是基于glib,否则也是基于select的,glib在linux下用的poll。
29-
这些均不是平台最优的I/O复用。
30-
下一步,使用其他事件循环替代Qt默认的时间循环。
28+
重新设计下线程模型,现有的movetothread不是很好。
3129

3230
==============
3331
QLibeventTcpServer移到了old分支

Server/TcpServerer.pro

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ CONFIG += console
1414
CONFIG -= app_bundle
1515
CONFIG += C++11
1616

17-
SOURCES += main.cpp\
18-
tcpserver.cpp \
19-
tcpsocket.cpp \
20-
threadhandle.cpp
17+
SOURCES += $$PWD/main.cpp\
18+
$$PWD/tcpserver.cpp \
19+
$$PWD/tcpsocket.cpp \
20+
$$PWD/threadhandle.cpp
2121

2222
HEADERS += \
23-
tcpserver.h \
24-
tcpsocket.h \
25-
threadhandle.h
23+
$$PWD/tcpserver.h \
24+
$$PWD/tcpsocket.h \
25+
$$PWD/threadhandle.h
2626

27+
unix:include($$PWD/eventdispatcher_libev/eventdispatcher_libev.pri)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.a
2+
*.o
3+
*.moc
4+
*.prl
5+
*.pro.user
6+
moc_*.cpp
7+
Makefile
8+
Makefile.*
9+
/tests/tst_*
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "tests/qt_eventdispatcher_tests"]
2+
path = tests/qt_eventdispatcher_tests
3+
url = git://github.com/sjinks/qt_eventdispatcher_tests.git
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
language: cpp
2+
3+
compiler:
4+
- gcc
5+
- clang
6+
7+
branches:
8+
only:
9+
- master
10+
11+
before_install:
12+
- git submodule update --init --recursive
13+
14+
install:
15+
- sudo apt-get update -qq
16+
- sudo apt-get install -qq libqt4-dev libqt4-private-dev libev4 libev-dev
17+
18+
script:
19+
- ./build.sh
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#include <QtCore/QPair>
2+
#include <QtCore/QSocketNotifier>
3+
#include <QtCore/QThread>
4+
#include "eventdispatcher_libev.h"
5+
#include "eventdispatcher_libev_p.h"
6+
7+
8+
EventDispatcherLibEv::EventDispatcherLibEv(QObject* parent)
9+
: QAbstractEventDispatcher(parent), d_ptr(new EventDispatcherLibEvPrivate(this))
10+
{
11+
}
12+
13+
EventDispatcherLibEv::~EventDispatcherLibEv(void)
14+
{
15+
}
16+
17+
bool EventDispatcherLibEv::processEvents(QEventLoop::ProcessEventsFlags flags)
18+
{
19+
Q_D(EventDispatcherLibEv);
20+
return d->processEvents(flags);
21+
}
22+
23+
bool EventDispatcherLibEv::hasPendingEvents(void)
24+
{
25+
extern uint qGlobalPostedEventsCount();
26+
return qGlobalPostedEventsCount() > 0;
27+
}
28+
29+
void EventDispatcherLibEv::registerSocketNotifier(QSocketNotifier* notifier)
30+
{
31+
#ifndef QT_NO_DEBUG
32+
if (notifier->socket() < 0) {
33+
qWarning("QSocketNotifier: Internal error: sockfd < 0");
34+
return;
35+
}
36+
37+
if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
38+
qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
39+
return;
40+
}
41+
#endif
42+
43+
if (notifier->type() == QSocketNotifier::Exception) {
44+
return;
45+
}
46+
47+
Q_D(EventDispatcherLibEv);
48+
d->registerSocketNotifier(notifier);
49+
}
50+
51+
void EventDispatcherLibEv::unregisterSocketNotifier(QSocketNotifier* notifier)
52+
{
53+
#ifndef QT_NO_DEBUG
54+
if (notifier->socket() < 0) {
55+
qWarning("QSocketNotifier: Internal error: sockfd < 0");
56+
return;
57+
}
58+
59+
if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
60+
qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
61+
return;
62+
}
63+
#endif
64+
65+
// Short circuit, we do not support QSocketNotifier::Exception
66+
if (notifier->type() == QSocketNotifier::Exception) {
67+
return;
68+
}
69+
70+
Q_D(EventDispatcherLibEv);
71+
d->unregisterSocketNotifier(notifier);
72+
}
73+
74+
void EventDispatcherLibEv::registerTimer(int timerId,int interval,
75+
Qt::TimerType timerType,QObject* object)
76+
{
77+
#ifndef QT_NO_DEBUG
78+
if (timerId < 1 || interval < 0 || !object) {
79+
qWarning("%s: invalid arguments", Q_FUNC_INFO);
80+
return;
81+
}
82+
83+
if (object->thread() != this->thread() && this->thread() != QThread::currentThread()) {
84+
qWarning("%s: timers cannot be started from another thread", Q_FUNC_INFO);
85+
return;
86+
}
87+
#endif
88+
89+
Qt::TimerType type;
90+
type = timerType;
91+
92+
Q_D(EventDispatcherLibEv);
93+
if (interval) {
94+
d->registerTimer(timerId, interval, type, object);
95+
}
96+
else {
97+
d->registerZeroTimer(timerId, object);
98+
}
99+
}
100+
101+
bool EventDispatcherLibEv::unregisterTimer(int timerId)
102+
{
103+
#ifndef QT_NO_DEBUG
104+
if (timerId < 1) {
105+
qWarning("%s: invalid arguments", Q_FUNC_INFO);
106+
return false;
107+
}
108+
109+
if (this->thread() != QThread::currentThread()) {
110+
qWarning("%s: timers cannot be stopped from another thread", Q_FUNC_INFO);
111+
return false;
112+
}
113+
#endif
114+
115+
Q_D(EventDispatcherLibEv);
116+
return d->unregisterTimer(timerId);
117+
}
118+
119+
bool EventDispatcherLibEv::unregisterTimers(QObject* object)
120+
{
121+
#ifndef QT_NO_DEBUG
122+
if (!object) {
123+
qWarning("%s: invalid arguments", Q_FUNC_INFO);
124+
return false;
125+
}
126+
127+
if (object->thread() != this->thread() && this->thread() != QThread::currentThread()) {
128+
qWarning("%s: timers cannot be stopped from another thread", Q_FUNC_INFO);
129+
return false;
130+
}
131+
#endif
132+
133+
Q_D(EventDispatcherLibEv);
134+
return d->unregisterTimers(object);
135+
}
136+
137+
QList<QAbstractEventDispatcher::TimerInfo> EventDispatcherLibEv::registeredTimers(QObject* object) const
138+
{
139+
if (!object) {
140+
qWarning("%s: invalid argument", Q_FUNC_INFO);
141+
return QList<QAbstractEventDispatcher::TimerInfo>();
142+
}
143+
144+
Q_D(const EventDispatcherLibEv);
145+
return d->registeredTimers(object);
146+
}
147+
148+
int EventDispatcherLibEv::remainingTime(int timerId)
149+
{
150+
Q_D(const EventDispatcherLibEv);
151+
return d->remainingTime(timerId);
152+
}
153+
154+
void EventDispatcherLibEv::wakeUp(void)
155+
{
156+
Q_D(EventDispatcherLibEv);
157+
158+
if (d->m_wakeups.testAndSetAcquire(0, 1))
159+
{
160+
ev_async_send(d->m_base, &d->m_wakeup);
161+
}
162+
}
163+
164+
void EventDispatcherLibEv::interrupt(void)
165+
{
166+
Q_D(EventDispatcherLibEv);
167+
d->m_interrupt = true;
168+
this->wakeUp();
169+
}
170+
171+
void EventDispatcherLibEv::flush(void)
172+
{
173+
}
174+
175+
EventDispatcherLibEv::EventDispatcherLibEv(EventDispatcherLibEvPrivate& dd, QObject* parent)
176+
: QAbstractEventDispatcher(parent), d_ptr(&dd)
177+
{
178+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef EVENTDISPATCHER_LIBEV_H
2+
#define EVENTDISPATCHER_LIBEV_H
3+
4+
#include <QtCore/QAbstractEventDispatcher>
5+
6+
class EventDispatcherLibEvPrivate;
7+
8+
class EventDispatcherLibEv : public QAbstractEventDispatcher
9+
{
10+
Q_OBJECT
11+
public:
12+
explicit EventDispatcherLibEv(QObject* parent = 0);
13+
virtual ~EventDispatcherLibEv(void);
14+
15+
virtual bool processEvents(QEventLoop::ProcessEventsFlags flags);
16+
virtual bool hasPendingEvents(void);
17+
18+
virtual void registerSocketNotifier(QSocketNotifier* notifier);
19+
virtual void unregisterSocketNotifier(QSocketNotifier* notifier);
20+
21+
virtual void registerTimer(int timerId,int interval,
22+
Qt::TimerType timerType,QObject* object);
23+
24+
virtual bool unregisterTimer(int timerId);
25+
virtual bool unregisterTimers(QObject* object);
26+
virtual QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject* object) const;
27+
virtual int remainingTime(int timerId);
28+
29+
virtual void wakeUp(void);
30+
virtual void interrupt(void);
31+
virtual void flush(void);
32+
33+
protected:
34+
EventDispatcherLibEv(EventDispatcherLibEvPrivate& dd, QObject* parent = 0);
35+
36+
private:
37+
Q_DISABLE_COPY(EventDispatcherLibEv)
38+
Q_DECLARE_PRIVATE(EventDispatcherLibEv)
39+
QScopedPointer<EventDispatcherLibEvPrivate> d_ptr;
40+
};
41+
42+
#endif // EVENTDISPATCHER_LIBEV_H
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
HEADERS += \
2+
$$PWD/eventdispatcher_libev.h \
3+
$$PWD/eventdispatcher_libev_p.h
4+
SOURCES += \
5+
$$PWD/eventdispatcher_libev.cpp \
6+
$$PWD/eventdispatcher_libev_p.cpp \
7+
$$PWD/timers_p.cpp \
8+
$$PWD/socknot_p.cpp
9+
10+
LIBS += -lev
11+

0 commit comments

Comments
 (0)