3 #include <glog/logging.h>
6 #include <sys/select.h>
8 using std::chrono::duration_cast
;
9 using std::chrono::milliseconds
;
10 using std::chrono::seconds
;
11 using std::chrono::system_clock
;
12 using std::chrono::time_point
;
14 void POSIX::set_nonblocking(int fd
)
17 PCHECK((flags
= fcntl(fd
, F_GETFL
, 0)) != -1);
18 if (0 == (flags
& O_NONBLOCK
)) {
19 PCHECK(fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
) != -1);
23 bool POSIX::input_ready(int fd_in
, milliseconds wait
)
30 tv
.tv_sec
= duration_cast
<seconds
>(wait
).count();
31 tv
.tv_usec
= (wait
.count() % 1000) * 1000;
34 PCHECK((puts
= select(fd_in
+ 1, &fds
, nullptr, nullptr, &tv
)) != -1);
39 bool POSIX::output_ready(int fd_out
, milliseconds wait
)
46 tv
.tv_sec
= duration_cast
<seconds
>(wait
).count();
47 tv
.tv_usec
= (wait
.count() % 1000) * 1000;
50 PCHECK((puts
= select(fd_out
+ 1, nullptr, &fds
, nullptr, &tv
)) != -1);
55 std::streamsize
POSIX::read(int fd
,
58 std::function
<void(void)> read_hook
,
59 std::chrono::milliseconds timeout
,
62 auto const start
= system_clock::now();
63 auto const end_time
= start
+ timeout
;
66 auto const n_ret
= ::read(fd
, static_cast<void*>(s
), n
);
70 case EINTR
: break; // try read again
73 LOG(WARNING
) << "read(2) raised ECONNRESET";
77 PCHECK((errno
== EWOULDBLOCK
) || (errno
== EAGAIN
))
78 << "error from read(2)";
81 else if (n_ret
>= 0) {
85 auto const now
= system_clock::now();
87 auto const time_left
= duration_cast
<milliseconds
>(end_time
- now
);
89 if (input_ready(fd
, time_left
))
90 continue; // try read again
93 LOG(WARNING
) << "read(2) timed out";
98 std::streamsize
POSIX::write(int fd
,
101 std::chrono::milliseconds timeout
,
104 auto const start
= system_clock::now();
105 auto const end_time
= start
+ timeout
;
107 auto written
= std::streamsize
{};
110 auto const n_ret
= ::write(fd
, static_cast<const void*>(s
), n
- written
);
114 case EINTR
: break; // try write again
117 LOG(WARNING
) << "write(2) raised ECONNRESET";
121 PCHECK((errno
== EWOULDBLOCK
) || (errno
== EAGAIN
))
122 << "error from write(2)";
125 else if (n_ret
== 0) {
126 LOG(WARNING
) << "zero write";
135 auto const now
= system_clock::now();
136 if (now
< end_time
) {
137 auto const time_left
= duration_cast
<milliseconds
>(end_time
- now
);
138 if (output_ready(fd
, time_left
))
139 continue; // write some more
142 LOG(WARNING
) << "write(2) time out";