AsyncTimeout.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/io/async/AsyncTimeout.h>
  17. #include <folly/io/async/EventBase.h>
  18. #include <folly/io/async/EventUtil.h>
  19. #include <folly/io/async/Request.h>
  20. #include <assert.h>
  21. #include <glog/logging.h>
  22. namespace folly {
  23. AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
  24. : timeoutManager_(timeoutManager) {
  25. folly_event_set(
  26. &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
  27. event_.ev_base = nullptr;
  28. timeoutManager_->attachTimeoutManager(
  29. this, TimeoutManager::InternalEnum::NORMAL);
  30. }
  31. AsyncTimeout::AsyncTimeout(EventBase* eventBase) : timeoutManager_(eventBase) {
  32. folly_event_set(
  33. &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
  34. event_.ev_base = nullptr;
  35. if (eventBase) {
  36. timeoutManager_->attachTimeoutManager(
  37. this, TimeoutManager::InternalEnum::NORMAL);
  38. }
  39. }
  40. AsyncTimeout::AsyncTimeout(
  41. TimeoutManager* timeoutManager,
  42. InternalEnum internal)
  43. : timeoutManager_(timeoutManager) {
  44. folly_event_set(
  45. &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
  46. event_.ev_base = nullptr;
  47. timeoutManager_->attachTimeoutManager(this, internal);
  48. }
  49. AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
  50. : timeoutManager_(eventBase) {
  51. folly_event_set(
  52. &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
  53. event_.ev_base = nullptr;
  54. timeoutManager_->attachTimeoutManager(this, internal);
  55. }
  56. AsyncTimeout::AsyncTimeout() : timeoutManager_(nullptr) {
  57. folly_event_set(
  58. &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
  59. event_.ev_base = nullptr;
  60. }
  61. AsyncTimeout::~AsyncTimeout() {
  62. cancelTimeout();
  63. }
  64. bool AsyncTimeout::scheduleTimeout(TimeoutManager::timeout_type timeout) {
  65. assert(timeoutManager_ != nullptr);
  66. context_ = RequestContext::saveContext();
  67. return timeoutManager_->scheduleTimeout(this, timeout);
  68. }
  69. bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
  70. return scheduleTimeout(TimeoutManager::timeout_type(milliseconds));
  71. }
  72. void AsyncTimeout::cancelTimeout() {
  73. if (isScheduled()) {
  74. timeoutManager_->cancelTimeout(this);
  75. context_.reset();
  76. }
  77. }
  78. bool AsyncTimeout::isScheduled() const {
  79. return EventUtil::isEventRegistered(&event_);
  80. }
  81. void AsyncTimeout::attachTimeoutManager(
  82. TimeoutManager* timeoutManager,
  83. InternalEnum internal) {
  84. // This also implies no timeout is scheduled.
  85. assert(timeoutManager_ == nullptr);
  86. assert(timeoutManager->isInTimeoutManagerThread());
  87. timeoutManager_ = timeoutManager;
  88. timeoutManager_->attachTimeoutManager(this, internal);
  89. }
  90. void AsyncTimeout::attachEventBase(
  91. EventBase* eventBase,
  92. InternalEnum internal) {
  93. attachTimeoutManager(eventBase, internal);
  94. }
  95. void AsyncTimeout::detachTimeoutManager() {
  96. // Only allow the event base to be changed if the timeout is not
  97. // currently installed.
  98. if (isScheduled()) {
  99. // Programmer bug. Abort the program.
  100. LOG(FATAL) << "detachEventBase() called on scheduled timeout; aborting";
  101. }
  102. if (timeoutManager_) {
  103. timeoutManager_->detachTimeoutManager(this);
  104. timeoutManager_ = nullptr;
  105. }
  106. }
  107. void AsyncTimeout::detachEventBase() {
  108. detachTimeoutManager();
  109. }
  110. void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
  111. AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
  112. assert(libeventFdToFd(fd) == -1);
  113. assert(events == EV_TIMEOUT);
  114. // prevent unused variable warnings
  115. (void)fd;
  116. (void)events;
  117. // double check that ev_flags gets reset when the timeout is not running
  118. assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
  119. // this can't possibly fire if timeout->eventBase_ is nullptr
  120. timeout->timeoutManager_->bumpHandlingTime();
  121. RequestContextScopeGuard rctx(timeout->context_);
  122. timeout->timeoutExpired();
  123. }
  124. } // namespace folly