| 509 | } |
| 510 | |
| 511 | int bthread_timed_connect(int sockfd, const struct sockaddr* serv_addr, |
| 512 | socklen_t addrlen, const timespec* abstime) { |
| 513 | if (!abstime) { |
| 514 | return bthread_connect(sockfd, serv_addr, addrlen); |
| 515 | } |
| 516 | |
| 517 | bool is_blocking = butil::is_blocking(sockfd); |
| 518 | if (is_blocking) { |
| 519 | butil::make_non_blocking(sockfd); |
| 520 | } |
| 521 | // Scoped non-blocking. |
| 522 | auto guard = butil::MakeScopeGuard([is_blocking, sockfd]() { |
| 523 | if (is_blocking) { |
| 524 | butil::make_blocking(sockfd); |
| 525 | } |
| 526 | }); |
| 527 | |
| 528 | const int rc = ::connect(sockfd, serv_addr, addrlen); |
| 529 | if (rc == 0 || errno != EINPROGRESS) { |
| 530 | return rc; |
| 531 | } |
| 532 | #if defined(OS_LINUX) |
| 533 | if (bthread_fd_timedwait(sockfd, EPOLLOUT, abstime) < 0) { |
| 534 | #elif defined(OS_MACOSX) |
| 535 | if (bthread_fd_timedwait(sockfd, EVFILT_WRITE, abstime) < 0) { |
| 536 | #endif |
| 537 | return -1; |
| 538 | } |
| 539 | |
| 540 | if (butil::is_connected(sockfd) != 0) { |
| 541 | return -1; |
| 542 | } |
| 543 | |
| 544 | return 0; |
| 545 | } |
| 546 | |
| 547 | // This does not wake pthreads calling bthread_fd_*wait. |
| 548 | int bthread_close(int fd) { |
| 549 | return bthread::get_epoll_thread(fd).fd_close(fd); |
| 550 | } |
| 551 | |
| 552 | } // extern "C" |