annotate win64-msvc/include/kj/async-unix.h @ 135:38d1c0e7850b

Headers for KJ/Capnp Win32
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 26 Oct 2016 13:18:45 +0100
parents 42a73082be24
children 0f2d93caa50c
rev   line source
cannam@132 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@132 2 // Licensed under the MIT License:
cannam@132 3 //
cannam@132 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@132 5 // of this software and associated documentation files (the "Software"), to deal
cannam@132 6 // in the Software without restriction, including without limitation the rights
cannam@132 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@132 8 // copies of the Software, and to permit persons to whom the Software is
cannam@132 9 // furnished to do so, subject to the following conditions:
cannam@132 10 //
cannam@132 11 // The above copyright notice and this permission notice shall be included in
cannam@132 12 // all copies or substantial portions of the Software.
cannam@132 13 //
cannam@132 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@132 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@132 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@132 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@132 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@132 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@132 20 // THE SOFTWARE.
cannam@132 21
cannam@132 22 #ifndef KJ_ASYNC_UNIX_H_
cannam@132 23 #define KJ_ASYNC_UNIX_H_
cannam@132 24
cannam@132 25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
cannam@132 26 #pragma GCC system_header
cannam@132 27 #endif
cannam@132 28
cannam@132 29 #include "async.h"
cannam@132 30 #include "time.h"
cannam@132 31 #include "vector.h"
cannam@132 32 #include "io.h"
cannam@132 33 #include <signal.h>
cannam@132 34
cannam@132 35 #if __linux__ && !__BIONIC__ && !defined(KJ_USE_EPOLL)
cannam@132 36 // Default to epoll on Linux, except on Bionic (Android) which doesn't have signalfd.h.
cannam@132 37 #define KJ_USE_EPOLL 1
cannam@132 38 #endif
cannam@132 39
cannam@132 40 namespace kj {
cannam@132 41
cannam@132 42 class UnixEventPort: public EventPort {
cannam@132 43 // An EventPort implementation which can wait for events on file descriptors as well as signals.
cannam@132 44 // This API only makes sense on Unix.
cannam@132 45 //
cannam@132 46 // The implementation uses `poll()` or possibly a platform-specific API (e.g. epoll, kqueue).
cannam@132 47 // To also wait on signals without race conditions, the implementation may block signals until
cannam@132 48 // just before `poll()` while using a signal handler which `siglongjmp()`s back to just before
cannam@132 49 // the signal was unblocked, or it may use a nicer platform-specific API like signalfd.
cannam@132 50 //
cannam@132 51 // The implementation reserves a signal for internal use. By default, it uses SIGUSR1. If you
cannam@132 52 // need to use SIGUSR1 for something else, you must offer a different signal by calling
cannam@132 53 // setReservedSignal() at startup.
cannam@132 54 //
cannam@132 55 // WARNING: A UnixEventPort can only be used in the thread and process that created it. In
cannam@132 56 // particular, note that after a fork(), a UnixEventPort created in the parent process will
cannam@132 57 // not work correctly in the child, even if the parent ceases to use its copy. In particular
cannam@132 58 // note that this means that server processes which daemonize themselves at startup must wait
cannam@132 59 // until after daemonization to create a UnixEventPort.
cannam@132 60
cannam@132 61 public:
cannam@132 62 UnixEventPort();
cannam@132 63 ~UnixEventPort() noexcept(false);
cannam@132 64
cannam@132 65 class FdObserver;
cannam@132 66 // Class that watches an fd for readability or writability. See definition below.
cannam@132 67
cannam@132 68 Promise<siginfo_t> onSignal(int signum);
cannam@132 69 // When the given signal is delivered to this thread, return the corresponding siginfo_t.
cannam@132 70 // The signal must have been captured using `captureSignal()`.
cannam@132 71 //
cannam@132 72 // If `onSignal()` has not been called, the signal will remain blocked in this thread.
cannam@132 73 // Therefore, a signal which arrives before `onSignal()` was called will not be "missed" -- the
cannam@132 74 // next call to 'onSignal()' will receive it. Also, you can control which thread receives a
cannam@132 75 // process-wide signal by only calling `onSignal()` on that thread's event loop.
cannam@132 76 //
cannam@132 77 // The result of waiting on the same signal twice at once is undefined.
cannam@132 78
cannam@132 79 static void captureSignal(int signum);
cannam@132 80 // Arranges for the given signal to be captured and handled via UnixEventPort, so that you may
cannam@132 81 // then pass it to `onSignal()`. This method is static because it registers a signal handler
cannam@132 82 // which applies process-wide. If any other threads exist in the process when `captureSignal()`
cannam@132 83 // is called, you *must* set the signal mask in those threads to block this signal, otherwise
cannam@132 84 // terrible things will happen if the signal happens to be delivered to those threads. If at
cannam@132 85 // all possible, call `captureSignal()` *before* creating threads, so that threads you create in
cannam@132 86 // the future will inherit the proper signal mask.
cannam@132 87 //
cannam@132 88 // To un-capture a signal, simply install a different signal handler and then un-block it from
cannam@132 89 // the signal mask.
cannam@132 90
cannam@132 91 static void setReservedSignal(int signum);
cannam@132 92 // Sets the signal number which `UnixEventPort` reserves for internal use. If your application
cannam@132 93 // needs to use SIGUSR1, call this at startup (before any calls to `captureSignal()` and before
cannam@132 94 // constructing an `UnixEventPort`) to offer a different signal.
cannam@132 95
cannam@132 96 TimePoint steadyTime() { return frozenSteadyTime; }
cannam@132 97 Promise<void> atSteadyTime(TimePoint time);
cannam@132 98
cannam@132 99 // implements EventPort ------------------------------------------------------
cannam@132 100 bool wait() override;
cannam@132 101 bool poll() override;
cannam@132 102 void wake() const override;
cannam@132 103
cannam@132 104 private:
cannam@132 105 struct TimerSet; // Defined in source file to avoid STL include.
cannam@132 106 class TimerPromiseAdapter;
cannam@132 107 class SignalPromiseAdapter;
cannam@132 108
cannam@132 109 Own<TimerSet> timers;
cannam@132 110 TimePoint frozenSteadyTime;
cannam@132 111
cannam@132 112 SignalPromiseAdapter* signalHead = nullptr;
cannam@132 113 SignalPromiseAdapter** signalTail = &signalHead;
cannam@132 114
cannam@132 115 TimePoint currentSteadyTime();
cannam@132 116 void processTimers();
cannam@132 117 void gotSignal(const siginfo_t& siginfo);
cannam@132 118
cannam@132 119 friend class TimerPromiseAdapter;
cannam@132 120
cannam@132 121 #if KJ_USE_EPOLL
cannam@132 122 AutoCloseFd epollFd;
cannam@132 123 AutoCloseFd signalFd;
cannam@132 124 AutoCloseFd eventFd; // Used for cross-thread wakeups.
cannam@132 125
cannam@132 126 sigset_t signalFdSigset;
cannam@132 127 // Signal mask as currently set on the signalFd. Tracked so we can detect whether or not it
cannam@132 128 // needs updating.
cannam@132 129
cannam@132 130 bool doEpollWait(int timeout);
cannam@132 131
cannam@132 132 #else
cannam@132 133 class PollContext;
cannam@132 134
cannam@132 135 FdObserver* observersHead = nullptr;
cannam@132 136 FdObserver** observersTail = &observersHead;
cannam@132 137
cannam@132 138 unsigned long long threadId; // actually pthread_t
cannam@132 139 #endif
cannam@132 140 };
cannam@132 141
cannam@132 142 class UnixEventPort::FdObserver {
cannam@132 143 // Object which watches a file descriptor to determine when it is readable or writable.
cannam@132 144 //
cannam@132 145 // For listen sockets, "readable" means that there is a connection to accept(). For everything
cannam@132 146 // else, it means that read() (or recv()) will return data.
cannam@132 147 //
cannam@132 148 // The presence of out-of-band data should NOT fire this event. However, the event may
cannam@132 149 // occasionally fire spuriously (when there is actually no data to read), and one thing that can
cannam@132 150 // cause such spurious events is the arrival of OOB data on certain platforms whose event
cannam@132 151 // interfaces fail to distinguish between regular and OOB data (e.g. Mac OSX).
cannam@132 152 //
cannam@132 153 // WARNING: The exact behavior of this class differs across systems, since event interfaces
cannam@132 154 // vary wildly. Be sure to read the documentation carefully and avoid depending on unspecified
cannam@132 155 // behavior. If at all possible, use the higher-level AsyncInputStream interface instead.
cannam@132 156
cannam@132 157 public:
cannam@132 158 enum Flags {
cannam@132 159 OBSERVE_READ = 1,
cannam@132 160 OBSERVE_WRITE = 2,
cannam@132 161 OBSERVE_URGENT = 4,
cannam@132 162 OBSERVE_READ_WRITE = OBSERVE_READ | OBSERVE_WRITE
cannam@132 163 };
cannam@132 164
cannam@132 165 FdObserver(UnixEventPort& eventPort, int fd, uint flags);
cannam@132 166 // Begin watching the given file descriptor for readability. Only one ReadObserver may exist
cannam@132 167 // for a given file descriptor at a time.
cannam@132 168
cannam@132 169 ~FdObserver() noexcept(false);
cannam@132 170
cannam@132 171 KJ_DISALLOW_COPY(FdObserver);
cannam@132 172
cannam@132 173 Promise<void> whenBecomesReadable();
cannam@132 174 // Resolves the next time the file descriptor transitions from having no data to read to having
cannam@132 175 // some data to read.
cannam@132 176 //
cannam@132 177 // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error
cannam@132 178 // to call this method when there is already data in the read buffer which has been there since
cannam@132 179 // prior to the last turn of the event loop or prior to creation FdWatcher. In this case, it is
cannam@132 180 // unspecified whether the promise will ever resolve -- it depends on the underlying event
cannam@132 181 // mechanism being used.
cannam@132 182 //
cannam@132 183 // In order to avoid this problem, make sure that you only call `whenBecomesReadable()`
cannam@132 184 // only at times when you know the buffer is empty. You know this for sure when one of the
cannam@132 185 // following happens:
cannam@132 186 // * read() or recv() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode
cannam@132 187 // enabled on the fd!)
cannam@132 188 // * The file descriptor is a regular byte-oriented object (like a socket or pipe),
cannam@132 189 // read() or recv() returns fewer than the number of bytes requested, and `atEndHint()`
cannam@132 190 // returns false. This can only happen if the buffer is empty but EOF is not reached. (Note,
cannam@132 191 // though, that for record-oriented file descriptors like Linux's inotify interface, this
cannam@132 192 // rule does not hold, because it could simply be that the next record did not fit into the
cannam@132 193 // space available.)
cannam@132 194 //
cannam@132 195 // It is an error to call `whenBecomesReadable()` again when the promise returned previously
cannam@132 196 // has not yet resolved. If you do this, the previous promise may throw an exception.
cannam@132 197
cannam@132 198 inline Maybe<bool> atEndHint() { return atEnd; }
cannam@132 199 // Returns true if the event system has indicated that EOF has been received. There may still
cannam@132 200 // be data in the read buffer, but once that is gone, there's nothing left.
cannam@132 201 //
cannam@132 202 // Returns false if the event system has indicated that EOF had NOT been received as of the
cannam@132 203 // last turn of the event loop.
cannam@132 204 //
cannam@132 205 // Returns nullptr if the event system does not know whether EOF has been reached. In this
cannam@132 206 // case, the only way to know for sure is to call read() or recv() and check if it returns
cannam@132 207 // zero.
cannam@132 208 //
cannam@132 209 // This hint may be useful as an optimization to avoid an unnecessary system call.
cannam@132 210
cannam@132 211 Promise<void> whenBecomesWritable();
cannam@132 212 // Resolves the next time the file descriptor transitions from having no space available in the
cannam@132 213 // write buffer to having some space available.
cannam@132 214 //
cannam@132 215 // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error
cannam@132 216 // to call this method when there is already space in the write buffer which has been there
cannam@132 217 // since prior to the last turn of the event loop or prior to creation FdWatcher. In this case,
cannam@132 218 // it is unspecified whether the promise will ever resolve -- it depends on the underlying
cannam@132 219 // event mechanism being used.
cannam@132 220 //
cannam@132 221 // In order to avoid this problem, make sure that you only call `whenBecomesWritable()`
cannam@132 222 // only at times when you know the buffer is full. You know this for sure when one of the
cannam@132 223 // following happens:
cannam@132 224 // * write() or send() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode
cannam@132 225 // enabled on the fd!)
cannam@132 226 // * write() or send() succeeds but accepts fewer than the number of bytes provided. This can
cannam@132 227 // only happen if the buffer is full.
cannam@132 228 //
cannam@132 229 // It is an error to call `whenBecomesWritable()` again when the promise returned previously
cannam@132 230 // has not yet resolved. If you do this, the previous promise may throw an exception.
cannam@132 231
cannam@132 232 Promise<void> whenUrgentDataAvailable();
cannam@132 233 // Resolves the next time the file descriptor's read buffer contains "urgent" data.
cannam@132 234 //
cannam@132 235 // The conditions for availability of urgent data are specific to the file descriptor's
cannam@132 236 // underlying implementation.
cannam@132 237 //
cannam@132 238 // It is an error to call `whenUrgentDataAvailable()` again when the promise returned previously
cannam@132 239 // has not yet resolved. If you do this, the previous promise may throw an exception.
cannam@132 240 //
cannam@132 241 // WARNING: This has some known weird behavior on macOS. See
cannam@132 242 // https://github.com/sandstorm-io/capnproto/issues/374.
cannam@132 243
cannam@132 244 private:
cannam@132 245 UnixEventPort& eventPort;
cannam@132 246 int fd;
cannam@132 247 uint flags;
cannam@132 248
cannam@132 249 kj::Maybe<Own<PromiseFulfiller<void>>> readFulfiller;
cannam@132 250 kj::Maybe<Own<PromiseFulfiller<void>>> writeFulfiller;
cannam@132 251 kj::Maybe<Own<PromiseFulfiller<void>>> urgentFulfiller;
cannam@132 252 // Replaced each time `whenBecomesReadable()` or `whenBecomesWritable()` is called. Reverted to
cannam@132 253 // null every time an event is fired.
cannam@132 254
cannam@132 255 Maybe<bool> atEnd;
cannam@132 256
cannam@132 257 void fire(short events);
cannam@132 258
cannam@132 259 #if !KJ_USE_EPOLL
cannam@132 260 FdObserver* next;
cannam@132 261 FdObserver** prev;
cannam@132 262 // Linked list of observers which currently have a non-null readFulfiller or writeFulfiller.
cannam@132 263 // If `prev` is null then the observer is not currently in the list.
cannam@132 264
cannam@132 265 short getEventMask();
cannam@132 266 #endif
cannam@132 267
cannam@132 268 friend class UnixEventPort;
cannam@132 269 };
cannam@132 270
cannam@132 271 } // namespace kj
cannam@132 272
cannam@132 273 #endif // KJ_ASYNC_UNIX_H_