Sponge
CS144's user-space TCP library
|
Waits for events on file descriptors and executes corresponding callbacks. More...
#include <eventloop.hh>
Classes | |
class | Rule |
Specifies a condition and callback that an EventLoop should handle. More... | |
Public Types | |
enum | Direction : short { Direction::In = POLLIN, Direction::Out = POLLOUT } |
Indicates interest in reading (In) or writing (Out) a polled fd. More... | |
enum | Result { Result::Success, Result::Timeout, Result::Exit } |
Returned by each call to EventLoop::wait_next_event. More... | |
Public Member Functions | |
void | add_rule (const FileDescriptor &fd, const Direction direction, const CallbackT &callback, const InterestT &interest=[] { return true;}, const CallbackT &cancel=[] {}) |
Add a rule whose callback will be called when fd is ready in the specified Direction. More... | |
Result | wait_next_event (const int timeout_ms) |
Calls poll(2) and then executes callback for each ready fd. More... | |
Private Types | |
using | CallbackT = std::function< void(void)> |
Callback for ready Rule::fd. More... | |
using | InterestT = std::function< bool(void)> |
true return indicates Rule::fd should be polled. More... | |
Private Attributes | |
std::list< Rule > | _rules {} |
All rules that have been added and not canceled. More... | |
Waits for events on file descriptors and executes corresponding callbacks.
An EventLoop holds a std::list of Rule objects. Each time EventLoop::wait_next_event is executed, the EventLoop uses the Rule objects to construct a call to poll(2).
When a Rule is installed using EventLoop::add_rule, it will be polled for the specified Rule::direction whenver the Rule::interest callback returns true
, until Rule::fd is no longer readable (for Rule::direction == Direction::In) or writable (for Rule::direction == Direction::Out). Once this occurs, the Rule is canceled, i.e., the EventLoop deletes it.
A Rule installed using EventLoop::add_cancelable_rule will be polled and canceled under the same conditions, with the additional condition that if Rule::callback returns true
, the Rule will be canceled.
Definition at line 12 of file eventloop.hh.
|
private |
Callback for ready Rule::fd.
Definition at line 21 of file eventloop.hh.
|
private |
true
return indicates Rule::fd should be polled.
Definition at line 22 of file eventloop.hh.
|
strong |
Indicates interest in reading (In) or writing (Out) a polled fd.
Enumerator | |
---|---|
In | Callback will be triggered when Rule::fd is readable. |
Out | Callback will be triggered when Rule::fd is writable. |
Definition at line 15 of file eventloop.hh.
|
strong |
Returned by each call to EventLoop::wait_next_event.
Enumerator | |
---|---|
Success | At least one Rule was triggered. |
Timeout | No rules were triggered before timeout. |
Exit | All rules have been canceled or were uninterested; make no further calls to EventLoop::wait_next_event. |
Definition at line 43 of file eventloop.hh.
void EventLoop::add_rule | ( | const FileDescriptor & | fd, |
const Direction | direction, | ||
const CallbackT & | callback, | ||
const InterestT & | interest = [] { return true; } , |
||
const CallbackT & | cancel = [] {} |
||
) |
Add a rule whose callback will be called when fd
is ready in the specified Direction.
[in] | fd | is the FileDescriptor to be polled |
[in] | direction | indicates whether to poll for reading (Direction::In) or writing (Direction::Out) |
[in] | callback | is called when fd is ready. |
[in] | interest | is called by EventLoop::wait_next_event. If it returns true , fd will be polled, otherwise fd will be ignored only for this execution of `wait_next_event. |
[in] | cancel | is called when the rule is cancelled (e.g. on hangup, EOF, or closure). |
Definition at line 23 of file eventloop.cc.
EventLoop::Result EventLoop::wait_next_event | ( | const int | timeout_ms | ) |
Calls poll(2) and then executes callback for each ready fd.
[in] | timeout_ms | is the timeout value passed to poll(2); wait_next_event returns Result::Timeout if no fd is ready after the timeout expires. |
For each Rule, this function first calls Rule::interest; if true
, Rule::fd is added to the list of file descriptors to be polled for readability (if Rule::direction == Direction::In) or writability (if Rule::direction == Direction::Out) unless Rule::fd has reached EOF, in which case the Rule is canceled (i.e., deleted from EventLoop::_rules).
Next, this function calls poll(2) with timeout value timeout_ms
.
Then, for each ready file descriptor, this function calls Rule::callback. If fd reaches EOF or if the Rule was registered using EventLoop::add_cancelable_rule and Rule::callback returns true, this Rule is canceled.
If an error occurs during polling, this function throws a std::runtime_error.
If a signal(7) was caught during polling or if EventLoop::_rules becomes empty, this function returns Result::Exit.
If a timeout occurred while polling (i.e., no fd became ready), this function returns Result::Timeout.
Otherwise, this function returns Result::Success.
IMPORTANT: every call to Rule::callback must read from or write to Rule::fd, or the interest
callback must stop returning true after the callback completes. If none of these conditions occur, EventLoop::wait_next_event will throw std::runtime_error. This is because poll(2) is level triggered, so failing to act on a ready file descriptor will result in a busy loop (poll returns on a ready file descriptor; file descriptor is not read or written, so it is still ready; the next call to poll will immediately return).
Definition at line 61 of file eventloop.cc.
All rules that have been added and not canceled.
Definition at line 39 of file eventloop.hh.