File indexing completed on 2024-05-19 13:30:29
0001 /* 0002 Copyright (C) 2017 Andreas Hartmetz <ahartmetz@gmail.com> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LGPL. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 0019 Alternatively, this file is available under the Mozilla Public License 0020 Version 1.1. You may obtain a copy of the License at 0021 http://www.mozilla.org/MPL/ 0022 */ 0023 0024 #include "foreigneventloopintegrator.h" 0025 0026 #include "eventdispatcher_p.h" 0027 #include "ieventpoller.h" 0028 #include "iioeventlistener.h" 0029 0030 #include <cassert> 0031 #include <unordered_map> 0032 0033 class ForeignEventLoopIntegratorPrivate : public IEventPoller 0034 { 0035 public: 0036 ForeignEventLoopIntegratorPrivate(ForeignEventLoopIntegrator *integrator, EventDispatcher *dispatcher); 0037 //virtual ~ForeignEventLoopIntegratorPrivate(); 0038 0039 IEventPoller::InterruptAction poll(int timeout = -1) override; 0040 // interrupt the waiting for events (from another thread) 0041 void interrupt(InterruptAction action) override; 0042 0043 void addFileDescriptor(FileDescriptor fd, uint32 ioRw) override; 0044 void removeFileDescriptor(FileDescriptor fd) override; 0045 void setReadWriteInterest(FileDescriptor fd, uint32 ioRw) override; 0046 0047 // public accessor for protected member variable 0048 EventDispatcher *dispatcher() const { return m_dispatcher; } 0049 0050 bool exiting = false; 0051 ForeignEventLoopIntegrator *m_integrator; 0052 0053 std::unordered_map<FileDescriptor, uint32 /* ioRW */> m_fds; 0054 }; 0055 0056 ForeignEventLoopIntegratorPrivate::ForeignEventLoopIntegratorPrivate(ForeignEventLoopIntegrator *integrator, 0057 EventDispatcher *dispatcher) 0058 : IEventPoller(dispatcher), 0059 m_integrator(integrator) 0060 { 0061 } 0062 0063 IEventPoller::InterruptAction ForeignEventLoopIntegratorPrivate::poll(int /* timeout */) 0064 { 0065 // do nothing, it can't possibly work (and it is *sometimes* a benign error to call this) 0066 return IEventPoller::NoInterrupt; 0067 } 0068 0069 void ForeignEventLoopIntegratorPrivate::interrupt(InterruptAction /* action */) 0070 { 0071 // do nothing, it can't possibly work (and it is *sometimes* a benign error to call this) 0072 } 0073 0074 void ForeignEventLoopIntegratorPrivate::addFileDescriptor(FileDescriptor fd, uint32 ioRw) 0075 { 0076 if (!exiting) { 0077 m_fds.emplace(fd, 0); 0078 if (ioRw) { 0079 setReadWriteInterest(fd, ioRw); 0080 } 0081 } 0082 } 0083 0084 void ForeignEventLoopIntegratorPrivate::removeFileDescriptor(FileDescriptor fd) 0085 { 0086 if (!exiting) { 0087 setReadWriteInterest(fd, 0); 0088 m_fds.erase(fd); 0089 } 0090 } 0091 0092 void ForeignEventLoopIntegratorPrivate::setReadWriteInterest(FileDescriptor fd, uint32 ioRw) 0093 { 0094 if (exiting) { 0095 return; 0096 } 0097 const uint32 oldRw = m_fds.at(fd); 0098 const bool oldRead = oldRw & uint32(IO::RW::Read); 0099 const bool read = ioRw & uint32(IO::RW::Read); 0100 if (oldRead != read) { 0101 m_integrator->setWatchRead(fd, read); 0102 } 0103 const bool oldWrite = oldRw & uint32(IO::RW::Write); 0104 const bool write = ioRw & uint32(IO::RW::Write); 0105 if (oldWrite != write) { 0106 m_integrator->setWatchWrite(fd, write); 0107 } 0108 m_fds.at(fd) = ioRw; 0109 } 0110 0111 ForeignEventLoopIntegrator::ForeignEventLoopIntegrator() 0112 : d(nullptr) 0113 { 0114 } 0115 0116 IEventPoller *ForeignEventLoopIntegrator::connectToDispatcher(EventDispatcher *dispatcher) 0117 { 0118 assert(!d); // this is a one-time operation 0119 d = new ForeignEventLoopIntegratorPrivate(this, dispatcher); 0120 return d; 0121 } 0122 0123 ForeignEventLoopIntegrator::~ForeignEventLoopIntegrator() 0124 { 0125 d->exiting = true; // try to prevent surprising states during shutdown, including of d->m_fds 0126 0127 // removeAllWatches() must be called from a derived class that implements the in this class pure 0128 // virtual methods setWatchRead(), setWatchWrite(), and watchTimeout(). During destruction, the 0129 // subclass data has already been destroyed and the vtable is the one of this class. 0130 //removeAllWatches(); 0131 } 0132 0133 void ForeignEventLoopIntegrator::removeAllWatches() 0134 { 0135 for (auto it = d->m_fds.begin(); it != d->m_fds.end(); ++it) { 0136 if (it->second & uint32(IO::RW::Read)) { 0137 setWatchRead(it->first, false); 0138 } 0139 if (it->second & uint32(IO::RW::Write)) { 0140 setWatchWrite(it->first, false); 0141 } 0142 it->second = 0; 0143 } 0144 watchTimeout(-1); 0145 if (d) { 0146 d->m_integrator = nullptr; 0147 delete d; 0148 d = nullptr; 0149 } 0150 } 0151 0152 bool ForeignEventLoopIntegrator::exiting() const 0153 { 0154 return d->exiting; 0155 } 0156 0157 void ForeignEventLoopIntegrator::handleTimeout() 0158 { 0159 if (!d->exiting) { 0160 EventDispatcherPrivate::get(d->dispatcher())->triggerDueTimers(); 0161 } 0162 } 0163 0164 void ForeignEventLoopIntegrator::handleReadyRead(int fd) 0165 { 0166 if (!d->exiting) { 0167 EventDispatcherPrivate::get(d->dispatcher())->notifyListenerForIo(fd, IO::RW::Read); 0168 } 0169 } 0170 0171 void ForeignEventLoopIntegrator::handleReadyWrite(int fd) 0172 { 0173 if (!d->exiting) { 0174 EventDispatcherPrivate::get(d->dispatcher())->notifyListenerForIo(fd, IO::RW::Write); 0175 } 0176 }