| 81 | |
| 82 | |
| 83 | Future<size_t> write(int_fd fd, const void* data, size_t size) |
| 84 | { |
| 85 | // TODO(benh): Let the system calls do what ever they're supposed to |
| 86 | // rather than return 0 here? |
| 87 | if (size == 0) { |
| 88 | return 0; |
| 89 | } |
| 90 | |
| 91 | return loop( |
| 92 | None(), |
| 93 | [=]() -> Future<Option<size_t>> { |
| 94 | ssize_t length = os::write(fd, data, size); |
| 95 | |
| 96 | if (length < 0) { |
| 97 | #ifdef __WINDOWS__ |
| 98 | WindowsSocketError error; |
| 99 | #else |
| 100 | ErrnoError error; |
| 101 | #endif // __WINDOWS__ |
| 102 | |
| 103 | if (!net::is_restartable_error(error.code) && |
| 104 | !net::is_retryable_error(error.code)) { |
| 105 | return Failure(error.message); |
| 106 | } |
| 107 | |
| 108 | return None(); |
| 109 | } |
| 110 | |
| 111 | return length; |
| 112 | }, |
| 113 | [=](const Option<size_t>& length) -> Future<ControlFlow<size_t>> { |
| 114 | // Restart/retry if we don't yet have a result. |
| 115 | if (length.isNone()) { |
| 116 | return io::poll(fd, io::WRITE) |
| 117 | .then([](short event) -> ControlFlow<size_t> { |
| 118 | CHECK_EQ(io::WRITE, event); |
| 119 | return Continue(); |
| 120 | }); |
| 121 | } |
| 122 | return Break(length.get()); |
| 123 | }); |
| 124 | } |
| 125 | |
| 126 | |
| 127 | Try<Nothing> prepare_async(int_fd fd) |