Compare commits

..

No commits in common. "dist" and "v1.0.2" have entirely different histories.
dist ... v1.0.2

4 changed files with 1844 additions and 1600 deletions

28
LICENSE
View File

@ -1,28 +0,0 @@
wepoll - epoll for Windows
https://github.com/piscisaureus/wepoll
Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

167
README.md
View File

@ -1,18 +1,18 @@
# wepoll - epoll for windows
[![][ci status badge]][ci status link]
This library implements the [epoll][man epoll] API for Windows
applications. It is fast and scalable, and it closely resembles the API
and behavior of Linux' epoll.
This library implements the
[epoll](http://man7.org/linux/man-pages/man7/epoll.7.html) API for
Windows applications. It attempts to be efficient, and to match the
Linux API and as closely as possible.
## Rationale
Unlike Linux, OS X, and many other operating systems, Windows doesn't
have a good API for receiving socket state notifications. It only
supports the `select` and `WSAPoll` APIs, but they
[don't scale][select scale] and suffer from
[other issues][wsapoll broken].
[don't scale](https://daniel.haxx.se/docs/poll-vs-select.html)
and suffer from
[other issues](https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/).
Using I/O completion ports isn't always practical when software is
designed to be cross-platform. Wepoll offers an alternative that is
@ -21,40 +21,37 @@ to run on Linux.
## Features
* Can poll 100000s of sockets efficiently.
* Fully thread-safe.
* Multiple threads can poll the same epoll port.
* Sockets can be added to multiple epoll sets.
* All epoll events (`EPOLLIN`, `EPOLLOUT`, `EPOLLPRI`, `EPOLLRDHUP`)
are supported.
* Level-triggered and one-shot (`EPOLLONESTHOT`) modes are supported
* Trivial to embed: you need [only two files][dist].
* can poll 100000s of sockets efficiently
* fully thread safe
* multiple threads can poll the same epoll port
* sockets can be added to multiple epoll sets
* polling for `EPOLLIN`, `EPOLLOUT`, `EPOLLPRI`, `EPOLLRDHUP`,
`EPOLLHUP`, and `EPOLLERR` events
* `EPOLLONESTHOT` flag
## Limitations
* Only works with sockets.
* Edge-triggered (`EPOLLET`) mode isn't supported.
* only works with sockets
* some modes not suported: `EPOLLET`, `EPOLLEXCLUSIVE`
## How to use
The library is [distributed][dist] as a single source file
([wepoll.c][wepoll.c]) and a single header file ([wepoll.h][wepoll.h]).<br>
Compile the .c file as part of your project, and include the header wherever
needed.
The library is distributed as a single source file (wepoll.c) and a
single header file (wepoll.h). Compile the .c file as part of your
project, and include the header wherever needed.
## Compatibility
* Requires Windows Vista or higher.
* Can be compiled with recent versions of MSVC, Clang, and GCC.
* Requires Windows 7 or higher.
* Can be compiled with recent versions of MSVC and Clang.
* GCC (mingw) should work (but is untested).
## API
## API notes
### General remarks
### General
* The epoll port is a `HANDLE`, not a file descriptor.
* All functions set both `errno` and `GetLastError()` on failure.
* For more extensive documentation, see the [epoll(7) man page][man epoll],
and the per-function man pages that are linked below.
### epoll_create/epoll_create1
@ -64,10 +61,10 @@ HANDLE epoll_create1(int flags);
```
* Create a new epoll instance (port).
* `size` is ignored but most be greater than zero.
* `size` is ignored but most be nonzero.
* `flags` must be zero as there are no supported flags.
* Returns `NULL` on failure.
* [Linux man page][man epoll_create]
* Returns `INVALID_HANDLE_VALUE` on failure.
* [man page](http://man7.org/linux/man-pages/man2/epoll_create.2.html)
### epoll_close
@ -89,22 +86,15 @@ int epoll_ctl(HANDLE ephnd,
```
* Control which socket events are monitored by an epoll port.
* `ephnd` must be a HANDLE created by
[`epoll_create()`](#epoll_createepoll_create1) or
[`epoll_create1()`](#epoll_createepoll_create1).
* `ephnd` must be a HANDLE created by `epoll_create` or `epoll_create1`.
* `op` must be one of `EPOLL_CTL_ADD`, `EPOLL_CTL_MOD`, `EPOLL_CTL_DEL`.
* `sock` must be a valid socket created by [`socket()`][msdn socket],
[`WSASocket()`][msdn wsasocket], or [`accept()`][msdn accept].
* `event` should be a pointer to a [`struct epoll_event`](#struct-epoll_event).<br>
If `op` is `EPOLL_CTL_DEL` then the `event` parameter is ignored, and it
may be `NULL`.
* Returns 0 on success, -1 on failure.
* It is recommended to always explicitly remove a socket from its epoll
set using `EPOLL_CTL_DEL` *before* closing it.<br>
As on Linux, closed sockets are automatically removed from the epoll set, but
wepoll may not be able to detect that a socket was closed until the next call
to [`epoll_wait()`](#epoll_wait).
* [Linux man page][man epoll_ctl]
set using `EPOLL_CTL_MOD` *before* closing it. As on Linux, sockets
are automatically removed from the epoll set when they are closed, but
wepoll may not be able to detect this until the next call to
`epoll_wait()`.
* TODO: expand
* [man page](http://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
### epoll_wait
@ -116,87 +106,10 @@ int epoll_wait(HANDLE ephnd,
```
* Receive socket events from an epoll port.
* `events` should point to a caller-allocated array of
[`epoll_event`](#struct-epoll_event) structs, which will receive the
reported events.
* `maxevents` is the maximum number of events that will be written to the
`events` array, and must be greater than zero.
* `timeout` specifies whether to block when no events are immediately available.
- `<0` block indefinitely
- `0` report any events that are already waiting, but don't block
- `≥1` block for at most N milliseconds
* Return value:
- `-1` an error occurred
- `0` timed out without any events to report
- `≥1` the number of events stored in the `events` buffer
* [Linux man page][man epoll_wait]
* Returns
- -1 on failure
- 0 when a timeout occurs
- \>0 the number of evens received
* TODO: expand
* [man page](http://man7.org/linux/man-pages/man2/epoll_wait.2.html)
### struct epoll_event
```c
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
```
```c
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
```
* The `events` field is a bit mask containing the events being
monitored/reported, and optional flags.<br>
Flags are accepted by [`epoll_ctl()`](#epoll_ctl), but they are not reported
back by [`epoll_wait()`](#epoll_wait).
* The `data` field can be used to associate application-specific information
with a socket; its value will be returned unmodified by
[`epoll_wait()`](#epoll_wait).
* [Linux man page][man epoll_ctl]
| Event | Description |
|---------------|----------------------------------------------------------------------|
| `EPOLLIN` | incoming data available, or incoming connection ready to be accepted |
| `EPOLLOUT` | ready to send data, or outgoing connection successfully established |
| `EPOLLRDHUP` | remote peer initiated graceful socket shutdown |
| `EPOLLPRI` | out-of-band data available for reading |
| `EPOLLERR` | socket error<sup>1</sup> |
| `EPOLLHUP` | socket hang-up<sup>1</sup> |
| `EPOLLRDNORM` | same as `EPOLLIN` |
| `EPOLLRDBAND` | same as `EPOLLPRI` |
| `EPOLLWRNORM` | same as `EPOLLOUT` |
| `EPOLLWRBAND` | same as `EPOLLOUT` |
| `EPOLLMSG` | never reported |
| Flag | Description |
|------------------|---------------------------|
| `EPOLLONESHOT` | report event(s) only once |
| `EPOLLET` | not supported by wepoll |
| `EPOLLEXCLUSIVE` | not supported by wepoll |
| `EPOLLWAKEUP` | not supported by wepoll |
<sup>1</sup>: the `EPOLLERR` and `EPOLLHUP` events may always be reported by
[`epoll_wait()`](#epoll_wait), regardless of the event mask that was passed to
[`epoll_ctl()`](#epoll_ctl).
[ci status badge]: https://ci.appveyor.com/api/projects/status/github/piscisaureus/wepoll?branch=master&svg=true
[ci status link]: https://ci.appveyor.com/project/piscisaureus/wepoll/branch/master
[dist]: https://github.com/piscisaureus/wepoll/tree/dist
[man epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
[man epoll_create]: http://man7.org/linux/man-pages/man2/epoll_create.2.html
[man epoll_ctl]: http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
[man epoll_wait]: http://man7.org/linux/man-pages/man2/epoll_wait.2.html
[msdn accept]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737526(v=vs.85).aspx
[msdn socket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
[msdn wsasocket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
[select scale]: https://daniel.haxx.se/docs/poll-vs-select.html
[wsapoll broken]: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
[wepoll.c]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.c
[wepoll.h]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.h

3189
wepoll.c

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/*
* wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll
* Copyright 2012-2017, Bert Belder. All rights reserved.
*
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
* All rights reserved.
* The red-black tree implementation:
* Copyright 2002 Niels Provos <provos@citi.umich.edu> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -39,32 +39,32 @@
#include <stdint.h>
enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1),
EPOLLOUT = (int) (1U << 2),
EPOLLERR = (int) (1U << 3),
EPOLLHUP = (int) (1U << 4),
EPOLLRDNORM = (int) (1U << 6),
EPOLLRDBAND = (int) (1U << 7),
EPOLLWRNORM = (int) (1U << 8),
EPOLLWRBAND = (int) (1U << 9),
EPOLLMSG = (int) (1U << 10), /* Never reported. */
EPOLLRDHUP = (int) (1U << 13),
EPOLLONESHOT = (int) (1U << 31)
EPOLLIN = 1 << 0,
EPOLLPRI = 1 << 1,
EPOLLOUT = 1 << 2,
EPOLLERR = 1 << 3,
EPOLLHUP = 1 << 4,
EPOLLRDNORM = 1 << 6,
EPOLLRDBAND = 1 << 7,
EPOLLWRNORM = 1 << 8,
EPOLLWRBAND = 1 << 9,
EPOLLMSG = 1 << 10,
EPOLLRDHUP = 1 << 13,
EPOLLONESHOT = 1 << 31
};
#define EPOLLIN (1U << 0)
#define EPOLLPRI (1U << 1)
#define EPOLLOUT (1U << 2)
#define EPOLLERR (1U << 3)
#define EPOLLHUP (1U << 4)
#define EPOLLRDNORM (1U << 6)
#define EPOLLRDBAND (1U << 7)
#define EPOLLWRNORM (1U << 8)
#define EPOLLWRBAND (1U << 9)
#define EPOLLMSG (1U << 10)
#define EPOLLRDHUP (1U << 13)
#define EPOLLONESHOT (1U << 31)
#define EPOLLIN EPOLLIN
#define EPOLLPRI EPOLLPRI
#define EPOLLOUT EPOLLOUT
#define EPOLLERR EPOLLERR
#define EPOLLHUP EPOLLHUP
#define EPOLLRDNORM EPOLLRDNORM
#define EPOLLRDBAND EPOLLRDBAND
#define EPOLLWRNORM EPOLLWRNORM
#define EPOLLWRBAND EPOLLWRBAND
#define EPOLLMSG EPOLLMSG
#define EPOLLRDHUP EPOLLRDHUP
#define EPOLLONESHOT EPOLLONESHOT
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_MOD 2
@ -78,12 +78,12 @@ typedef union epoll_data {
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
SOCKET sock;
HANDLE hnd;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events and flags */
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};