replace qt event loop with epoll
This commit is contained in:
		
							parent
							
								
									dfae73b1c5
								
							
						
					
					
						commit
						31c09e24d6
					
				
							
								
								
									
										132
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -5,6 +5,7 @@ | |||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
|  | #include <sys/epoll.h> | ||||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||||
| #include <sys/signalfd.h> | #include <sys/signalfd.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| @ -14,10 +15,10 @@ | |||||||
| #include <list> | #include <list> | ||||||
| #include <optional> | #include <optional> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <QGuiApplication> |  | ||||||
| #include <QSocketNotifier> |  | ||||||
| #include <wayland-client.h> | #include <wayland-client.h> | ||||||
| #include <wayland-cursor.h> | #include <wayland-cursor.h> | ||||||
|  | #include <QGuiApplication> | ||||||
|  | #include <QString> | ||||||
| #include "wlr-layer-shell-unstable-v1-client-protocol.h" | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | ||||||
| #include "xdg-shell-client-protocol.h" | #include "xdg-shell-client-protocol.h" | ||||||
| #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" | #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" | ||||||
| @ -44,10 +45,11 @@ struct Seat { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void waylandFlush(); | static void waylandFlush(); | ||||||
| static void waylandWriteReady(); |  | ||||||
| static void requireGlobal(const void *p, const char *name); | static void requireGlobal(const void *p, const char *name); | ||||||
| static void setupStatusFifo(); | static void setupStatusFifo(); | ||||||
| static void onStatus(); | static void onStatus(); | ||||||
|  | [[noreturn]] static void diesys(const char *why); | ||||||
|  | [[noreturn]] static void die(const char *why); | ||||||
| static void cleanup(); | static void cleanup(); | ||||||
| 
 | 
 | ||||||
| wl_display *display; | wl_display *display; | ||||||
| @ -65,9 +67,10 @@ static std::list<Monitor> monitors; | |||||||
| static std::list<Seat> seats; | static std::list<Seat> seats; | ||||||
| static QString lastStatus; | static QString lastStatus; | ||||||
| static std::string statusFifoName; | static std::string statusFifoName; | ||||||
|  | static int epoll {-1}; | ||||||
|  | static int displayFd {-1}; | ||||||
| static int statusFifoFd {-1}; | static int statusFifoFd {-1}; | ||||||
| static int statusFifoWriter {-1}; | static int statusFifoWriter {-1}; | ||||||
| static QSocketNotifier *displayWriteNotifier; |  | ||||||
| static bool quitting {false}; | static bool quitting {false}; | ||||||
| 
 | 
 | ||||||
| void view(Monitor &m, const Arg &arg) | void view(Monitor &m, const Arg &arg) | ||||||
| @ -245,28 +248,27 @@ static void setupStatusFifo() | |||||||
|         auto result = mkfifo(path.c_str(), 0666); |         auto result = mkfifo(path.c_str(), 0666); | ||||||
|         if (result == 0) { |         if (result == 0) { | ||||||
|             auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY); |             auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY); | ||||||
|             if (fd == -1) { |             if (fd < 0) { | ||||||
|                 perror("open status fifo reader"); |                 diesys("open status fifo reader"); | ||||||
|                 cleanup(); |  | ||||||
|                 exit(1); |  | ||||||
|             } |             } | ||||||
|             statusFifoName = path; |             statusFifoName = path; | ||||||
|             statusFifoFd = fd; |             statusFifoFd = fd; | ||||||
| 
 | 
 | ||||||
|             fd = open(path.c_str(), O_CLOEXEC | O_WRONLY); |             fd = open(path.c_str(), O_CLOEXEC | O_WRONLY); | ||||||
|             if (fd == -1) { |             if (fd < 0) { | ||||||
|                 perror("open status fifo writer"); |                 diesys("open status fifo writer"); | ||||||
|                 cleanup(); |  | ||||||
|                 exit(1); |  | ||||||
|             } |             } | ||||||
|             statusFifoWriter = fd; |             statusFifoWriter = fd; | ||||||
| 
 | 
 | ||||||
|             auto statusNotifier = new QSocketNotifier(statusFifoFd, QSocketNotifier::Read); |             epoll_event ev = {0}; | ||||||
|             statusNotifier->setEnabled(true); |             ev.events = EPOLLIN; | ||||||
|             QObject::connect(statusNotifier, &QSocketNotifier::activated, onStatus); |             ev.data.fd = statusFifoFd; | ||||||
|  |             if (epoll_ctl(epoll, EPOLL_CTL_ADD, statusFifoFd, &ev) < 0) { | ||||||
|  |                 diesys("epoll_ctl add status fifo"); | ||||||
|  |             } | ||||||
|             return; |             return; | ||||||
|         } else if (errno != EEXIST) { |         } else if (errno != EEXIST) { | ||||||
|             perror("mkfifo"); |             diesys("mkfifo"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -341,52 +343,87 @@ int main(int argc, char **argv) | |||||||
|     sigaddset(&blockedsigs, SIGTERM); |     sigaddset(&blockedsigs, SIGTERM); | ||||||
|     sigprocmask(SIG_BLOCK, &blockedsigs, nullptr); |     sigprocmask(SIG_BLOCK, &blockedsigs, nullptr); | ||||||
| 
 | 
 | ||||||
|     QGuiApplication app(argc, argv); |     QGuiApplication app {argc, argv}; | ||||||
|     QCoreApplication::setOrganizationName("tape software"); |  | ||||||
|     QCoreApplication::setOrganizationDomain("tapesoftware.net"); |  | ||||||
|     QCoreApplication::setApplicationName("somebar"); |  | ||||||
| 
 | 
 | ||||||
|  |     epoll_event epollEv = {0}; | ||||||
|  |     std::array<epoll_event, 5> epollEvents; | ||||||
|  |     epoll = epoll_create1(EPOLL_CLOEXEC); | ||||||
|  |     if (epoll < 0) { | ||||||
|  |         diesys("epoll_create1"); | ||||||
|  |     } | ||||||
|     int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK); |     int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK); | ||||||
|     if (sfd < 0) { |     if (sfd < 0) { | ||||||
|         perror("signalfd"); |         diesys("signalfd"); | ||||||
|         cleanup(); |     } | ||||||
|         exit(1); |     epollEv.events = EPOLLIN; | ||||||
|  |     epollEv.data.fd = sfd; | ||||||
|  |     if (epoll_ctl(epoll, EPOLL_CTL_ADD, sfd, &epollEv) < 0) { | ||||||
|  |         diesys("epoll_ctl add signalfd"); | ||||||
|     } |     } | ||||||
|     QSocketNotifier signalNotifier {sfd, QSocketNotifier::Read}; |  | ||||||
|     QObject::connect(&signalNotifier, &QSocketNotifier::activated, []() { quitting = true; }); |  | ||||||
| 
 | 
 | ||||||
|     display = wl_display_connect(NULL); |     display = wl_display_connect(nullptr); | ||||||
|     if (!display) { |     if (!display) { | ||||||
|         fprintf(stderr, "Failed to connect to Wayland display\n"); |         die("Failed to connect to Wayland display"); | ||||||
|         return 1; |  | ||||||
|     } |     } | ||||||
|  |     displayFd = wl_display_get_fd(display); | ||||||
| 
 | 
 | ||||||
|     auto registry = wl_display_get_registry(display); |     auto registry = wl_display_get_registry(display); | ||||||
|     wl_registry_add_listener(registry, ®istry_listener, nullptr); |     wl_registry_add_listener(registry, ®istry_listener, nullptr); | ||||||
|     wl_display_roundtrip(display); |     wl_display_roundtrip(display); | ||||||
|     onReady(); |     onReady(); | ||||||
| 
 | 
 | ||||||
|     QSocketNotifier displayReadNotifier(wl_display_get_fd(display), QSocketNotifier::Read); |     epollEv.events = EPOLLIN; | ||||||
|     displayReadNotifier.setEnabled(true); |     epollEv.data.fd = displayFd; | ||||||
|     QObject::connect(&displayReadNotifier, &QSocketNotifier::activated, [=]() { |     if (epoll_ctl(epoll, EPOLL_CTL_ADD, displayFd, &epollEv) < 0) { | ||||||
|         auto res = wl_display_dispatch(display); |         diesys("epoll_ctl add wayland_display"); | ||||||
|         if (res < 0) { |  | ||||||
|             perror("wl_display_dispatch"); |  | ||||||
|             cleanup(); |  | ||||||
|             exit(1); |  | ||||||
|     } |     } | ||||||
|     }); |  | ||||||
|     displayWriteNotifier = new QSocketNotifier(wl_display_get_fd(display), QSocketNotifier::Write); |  | ||||||
|     displayWriteNotifier->setEnabled(false); |  | ||||||
|     QObject::connect(displayWriteNotifier, &QSocketNotifier::activated, waylandWriteReady); |  | ||||||
| 
 | 
 | ||||||
|     while (!quitting) { |     while (!quitting) { | ||||||
|         waylandFlush(); |         waylandFlush(); | ||||||
|         app.processEvents(QEventLoop::WaitForMoreEvents); |         auto res = epoll_wait(epoll, epollEvents.data(), epollEvents.size(), -1); | ||||||
|  |         if (res < 0) { | ||||||
|  |             if (errno != EINTR) { | ||||||
|  |                 diesys("epoll_wait"); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             for (auto i=0; i<res; i++) { | ||||||
|  |                 auto &ev = epollEvents[i]; | ||||||
|  |                 if (ev.data.fd == displayFd) { | ||||||
|  |                     if (ev.events & EPOLLIN) { | ||||||
|  |                         if (wl_display_dispatch(display) < 0) { | ||||||
|  |                             die("wl_display_dispatch"); | ||||||
|  |                         } | ||||||
|  |                     } if (ev.events & EPOLLOUT) { | ||||||
|  |                         epollEv.events = EPOLLIN; | ||||||
|  |                         epollEv.data.fd = displayFd; | ||||||
|  |                         if (epoll_ctl(epoll, EPOLL_CTL_MOD, displayFd, &epollEv) < 0) { | ||||||
|  |                             diesys("epoll_ctl"); | ||||||
|  |                         } | ||||||
|  |                         waylandFlush(); | ||||||
|  |                     } | ||||||
|  |                 } else if (ev.data.fd == statusFifoFd) { | ||||||
|  |                     onStatus(); | ||||||
|  |                 } else if (ev.data.fd == sfd) { | ||||||
|  |                     quitting = true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     cleanup(); |     cleanup(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void die(const char *why) { | ||||||
|  |     fprintf(stderr, "%s\n", why); | ||||||
|  |     cleanup(); | ||||||
|  |     exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void diesys(const char *why) { | ||||||
|  |     perror(why); | ||||||
|  |     cleanup(); | ||||||
|  |     exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void cleanup() { | void cleanup() { | ||||||
|     if (!statusFifoName.empty()) { |     if (!statusFifoName.empty()) { | ||||||
|         unlink(statusFifoName.c_str()); |         unlink(statusFifoName.c_str()); | ||||||
| @ -397,14 +434,15 @@ void waylandFlush() | |||||||
| { | { | ||||||
|     wl_display_dispatch_pending(display); |     wl_display_dispatch_pending(display); | ||||||
|     if (wl_display_flush(display) < 0 && errno == EAGAIN) { |     if (wl_display_flush(display) < 0 && errno == EAGAIN) { | ||||||
|         displayWriteNotifier->setEnabled(true); |         epoll_event ev = {0}; | ||||||
|  |         ev.events = EPOLLIN | EPOLLOUT; | ||||||
|  |         ev.data.fd = displayFd; | ||||||
|  |         if (epoll_ctl(epoll, EPOLL_CTL_MOD, displayFd, &ev) < 0) { | ||||||
|  |             diesys("epoll_ctl"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| static void waylandWriteReady()  | 
 | ||||||
| { |  | ||||||
|     displayWriteNotifier->setEnabled(false); |  | ||||||
|     waylandFlush(); |  | ||||||
| } |  | ||||||
| static void requireGlobal(const void *p, const char *name) | static void requireGlobal(const void *p, const char *name) | ||||||
| { | { | ||||||
|     if (p) return; |     if (p) return; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user