diff --git a/docs/API-functions.md b/docs/API-functions.md index c9432f0cf..4fffc90d3 100644 --- a/docs/API-functions.md +++ b/docs/API-functions.md @@ -42,6 +42,8 @@ SRT API Functions * [srt_epoll_add_usock, srt_epoll_add_ssock, srt_epoll_update_usock, srt_epoll_update_ssock](#srt_epoll_add_usock-srt_epoll_add_ssock-srt_epoll_update_usock-srt_epoll_update_ssock) * [srt_epoll_remove_usock, srt_epoll_remove_ssock](#srt_epoll_remove_usock-srt_epoll_remove_ssock) * [srt_epoll_wait](#srt_epoll_wait) + * [srt_epoll_uwait](#srt_epoll_uwait) + * [srt_epoll_set](#srt_epoll_set) * [srt_epoll_release](#srt_epoll_release) - [**Logging control**](#Logging-control) * [srt_setloglevel](#srt_setloglevel) @@ -1194,8 +1196,36 @@ these two calls. * `eid`: epoll container id * `u`: SRT socket * `s`: system socket -* `events`: points to a variable set to epoll flags, or NULL if -you want to subscribe a socket for all possible events +* `events`: points to + * a variable set to epoll flags (see below) to use only selected events + * NULL if you want to subscribe a socket for all events in level-triggered mode + +Possible epoll flags are the following: + + * `SRT_EPOLL_IN`: report readiness for reading or incoming connection on a listener socket + * `SRT_EPOLL_OUT`: report readiness for writing or a successful connection + * `SRT_EPOLL_ERR`: report errors on the socket + * `SRT_EPOLL_ET`: the event will be edge-triggered + +The readiness states reported in by default are **level-triggered**. +If `SRT_EPOLL_ET` flag is specified, the reported states are +**edge-triggered**. Note that at this time the edge-triggered mode +is supported only for SRT sockets, not for system sockets. + +In the **edge-triggered** mode the function will only return socket states that +have changed since the last call. All events reported in particular call of +the waiting function will be cleared in the internal flags and will not be +reported until the internal signaling logic clears this state and raises it +again. + +In the **level-triggered** mode the function will always return the readiness +state as long as it lasts, until the internal signaling logic clear it. + +Note that when you use `SRT_EPOLL_ET` flag in one subscription call, it defines +edge-triggered mode for all events passed together with it. However, if you +want to have some events reported as edge-triggered and others as +level-triggered, you can do two separate subscriptions for the same socket. + - Returns: @@ -1203,7 +1233,7 @@ you want to subscribe a socket for all possible events - Errors: - * `SRT_EINVPOLLID`: `eid` designates no valid EID object + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container **BUG?**: for `add_ssock` the system error results in an empty `CUDTException()` call which actually results in `SRT_SUCCESS`. For cases like that the @@ -1228,7 +1258,7 @@ The `_ssock` suffix refers to a system socket. - Errors: - * `SRT_EINVPOLLID`: `eid` designates no valid EID object + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container ### srt_epoll_wait ``` @@ -1237,14 +1267,16 @@ int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, ``` Blocks the call until any readiness state occurs in the epoll container. -Mind that the readiness states reported in epoll are **permanent, not -edge-triggered**. Readiness can be on a socket in the container for the event type as per -subscription. The first readiness state causes this function to exit, but -all ready sockets are reported. This function blocks until the timeout. -If timeout is 0, it exits immediately after checking. If timeout is -1, -it blocks indefinitely until a readiness state occurs. +subscription. Note that in case when particular event was subscribed with +`SRT_EPOLL_ET` flag, this event, when once reported in this function, will +be cleared internally. + +The first readiness state causes this function to exit, but all ready sockets +are reported. This function blocks until the timeout specified in `msTimeOut` +parameter. If timeout is 0, it exits immediately after checking. If timeout is +-1, it blocks indefinitely until a readiness state occurs. * `eid`: epoll container * `readfds` and `rnum`: A pointer and length of an array to write SRT sockets that are read-ready @@ -1273,11 +1305,112 @@ of error has occurred on the socket. - Errors: - * `SRT_EINVPOLLID`: `eid` designates no valid EID object + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container * `SRT_ETIMEOUT`: Up to `msTimeOut` no sockets subscribed in `eid` were ready. This is reported only if `msTimeOut` was \>=0, otherwise the function waits indefinitely. +### srt_epoll_uwait +``` +int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +``` + +This function blocks a call until any readiness state occurs in the epoll +container. Unlike `srt_epoll_wait`, it can only be used with `eid` subscribed +to user sockets (SRT sockets), not system sockets. + +This function blocks until the timeout specified in `msTimeOut` parameter. If +timeout is 0, it exits immediately after checking. If timeout is -1, it blocks +indefinitely until a readiness state occurs. + +* `eid`: epoll container +* `fdsSet` : A pointer to an array of `SRT_EPOLL_EVENT` +* `fdsSize` : The size of the fdsSet array +* `msTimeOut` : Timeout specified in milliseconds, or special values (0 or -1): + * 0: Don't wait, return immediately (report any sockets currently ready) + * -1: Wait indefinitely. + +- Returns: + + * The number of user socket (SRT socket) state changes that have been reported +in `fdsSet`, if this number isn't greater than `fdsSize` + + * Otherwise the return value is `fdsSize` + 1. This means that there was not +enough space in the output array to report all events. For events subscribed with +`SRT_EPOLL_ET` flag only those will be cleared that were reported. Others will +wait for the next call. + + * If no readiness state was found on any socket and the timeout has passed, 0 +is returned (this is not possible when waiting indefinitely) + + * -1 in case of error + + +- Errors: + + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container + * `SRT_EINVPARAM`: One of possible usage errors: + * `fdsSize` is < 0 + * `fdsSize` is > 0 and `fdsSet` is a null pointer + * `eid` was subscribed to any system socket + +(IMPORTANT: this function reports timeout by returning 0, not by `SRT_ETIMEOUT` error.) + +The `SRT_EPOLL_EVENT` structure: + +``` +typedef struct SRT_EPOLL_EVENT_ +{ + SRTSOCKET fd; + int events; +} SRT_EPOLL_EVENT; +``` + +* `fd` : the user socket (SRT socket) +* `events` : event flags that report readiness of this socket - a combination +of `SRT_EPOLL_IN`, `SRT_EPOLL_OUT` and `SRT_EPOLL_ERR` - see [srt_epoll_add_usock](#srt_epoll_add_usock) +for details + +Note that when the `SRT_EPOLL_ERR` is set, the underlying socket error +can't be retrieved with `srt_getlasterror()`. The socket will be automatically +closed and its state can be verified with a call to `srt_getsockstate`. + +### srt_epoll_set +``` +int32_t srt_epoll_set(int eid, int32_t flags); +``` + +This function allows to set or retrieve flags that change the default +behavior of the epoll functions. All default values for these flags are 0. +The following flags are available: + +* `SRT_EPOLL_ENABLE_EMPTY`: allows the `srt_epoll_wait` and `srt_epoll_uwait` +functions to be called with the EID not subscribed to any socket. The default +behavior of these function is to report error in this case. + +* `SRT_EPOLL_ENABLE_OUTPUTCHECK`: Forces the `srt_epoll_wait` and `srt_epoll_uwait` +functions to check if the output array is not empty. For `srt_epoll_wait` it +is still allowed that either system or user array is empty, as long as EID +isn't subscribed to this type of socket/fd. `srt_epoll_uwait` only checks if +the general output array is not empty. + +- Parameters: + + * `eid`: the epoll container id + * `flags`: a nonzero set of the above flags, or special values: + * 0: clear all flags (set all defaults) + * -1: do not modify any flags + +- Returns: + +This function returns the state of the flags at the time before the call, +or a special value -1 in case when an error occurred. + +- Errors: + + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container + + ### srt_epoll_release ``` int srt_epoll_release(int eid); @@ -1293,7 +1426,7 @@ Deletes the epoll container. - Errors: - * `SRT_EINVPOLLID`: `eid` designates no valid EID object + * `SRT_EINVPOLLID`: `eid` parameter doesn't refer to a valid epoll container Logging control --------------- diff --git a/docs/API.md b/docs/API.md index 24e53480d..a06ed12eb 100644 --- a/docs/API.md +++ b/docs/API.md @@ -328,7 +328,11 @@ Synopsis int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); - + int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, + int64_t msTimeOut, + SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); + int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); + SRT Usage --------- @@ -340,14 +344,81 @@ user-level epoll that supports both SRT and system sockets. The `srt_epoll_update_{u|s}sock()` API functions described here are SRT additions to the UDT-derived `srt_epoll_add_{u|s}sock()` and `epoll_remove_{u|s}sock()` functions to atomically change the events of interest. For example, to remove -EPOLLOUT but keep EPOLLIN for a given socket with the existing API, the socket -must be removed from epoll and re-added. This cannot be done atomically, the -thread protection (against the epoll thread) being applied within each function -but unprotected between the two calls. It is then possible to lose a POLLIN -event if it fires while the socket is not in the epoll list. +`SRT_EPOLL_OUT` but keep `SRT_EPOLL_IN` for a given socket with the existing +API, the socket must be removed from epoll and re-added. This cannot be done +atomically, the thread protection (against the epoll thread) being applied +within each function but unprotected between the two calls. It is then possible +to lose an `SRT_EPOLL_IN` event if it fires while the socket is not in the +epoll list. + +Once the subscriptions are made, you can call an SRT polling function +(`srt_epoll_wait` or `srt_epoll_uwait`) that will block until an event +is raised on any of the subscribed sockets. This function will exit as +soon as st least one event is deteted or a timeout occurs. The timeout is +specified in `[ms]`, with two special values: + + - 0: check and report immediately (don't wait) + - -1: wait indefinitely (not interruptable, even by a system signal) + +There are some differences in the synopsis between these two: + +1. `srt_epoll_wait`: Both system and SRT sockets can be subscribed. This +function reports events on both socket types according to subscriptions, in +these arrays: + + - `readfds` and `lrfds`: subscribed for `IN` and `ERR` + - `writefds` and `lwfds`: subscribed for `OUT` and `ERR` + +where: + + - `readfds` and `writefds` report SRT sockets ("user" socket) + - `lrfds` and `lwfds` report system sockets + +Note: this function provides no straightforward possibility to report +sockets with an error. If you want to distinguish a report of readiness +for operation from an error report, the only way is to subscribe the +socket in only one direction (either `SRT_EPOLL_IN` or `SRT_EPOLL_OUT`, +but not both) and `SRT_EPOLL_ERR`, and then check the socket's presence +in the array for which's direction the socket wasn't subscribed (for +example, when an SRT socket is subscribed for `SRT_EPOLL_OUT | SRT_EPOLL_ERR`, +its presence in `readfds` means that an error is reported for it). +This need not be a big problem because when an error is reported on +a socket, an appearance as if it were ready for an operation, followed +by doing this operation, will simply result in an error from that +operation, so you can use it also as an alternative error check method. + +This function also reports error of type `SRT_ETIMEOUT` when no socket is +ready as the timeout elapses (including 0). This behavior is different in +`srt_epoll_uwait`. + +Note that in this function there's a loop that checks for socket readiness +every 10ms. Thus, the minimum poll timeout the function can reliably support, +when system sockets are involved, is also 10ms. The return time from a poll +function can only be quicker when there is an event raised on one of the active +SRT sockets. + + +2. `srt_epoll_uwait`: In this function only the SRT sockets can be subscribed +(it reports error if you pass an epoll id that is subscribed to system sockets). +This function waits for the first event on subscribed SRT socket and reports all +events collected at this moment in an array of this structure: + +``` +typedef struct SRT_EPOLL_EVENT_ +{ + SRTSOCKET fd; + int events; +} SRT_EPOLL_EVENT; + +``` + +Every item reports a single socket with all events as flags. + +When the timeout is not -1, and no sockets are ready until the timeout time +passes, this function returns 0. This behavior is different in `srt_epoll_wait`. The SRT EPoll system does not supports all features of Linux epoll. For -example, it only supports level-triggered events. +example, it only supports level-triggered events for system sockets. Options =======