fix stack usage in HHWhileTimer
authorMisha Shneerson <mshneer@fb.com>
Wed, 30 Mar 2016 05:42:54 +0000 (22:42 -0700)
committerFacebook Github Bot 0 <facebook-github-bot-0-bot@fb.com>
Wed, 30 Mar 2016 05:50:26 +0000 (22:50 -0700)
Summary:We should be able to use HHWheelTimer in fibers. So it should use way less stack.

Alternative solution to D3112305

Reviewed By: haijunz

Differential Revision: D3112558

fb-gh-sync-id: 3a52a37d9f9347639005fdf84524f7f8c3041918
fbshipit-source-id: 3a52a37d9f9347639005fdf84524f7f8c3041918

folly/io/async/HHWheelTimer.cpp

index 0078ae24fb104f1c46e61dc514ed3b5d54698792..f4110b02c69fb879bdeea51e7decc91394b2b37a 100644 (file)
@@ -229,29 +229,31 @@ size_t HHWheelTimer::cancelAll() {
   size_t count = 0;
 
   if (count_ != 0) {
-    decltype(buckets_) buckets;
-
-// Work around std::swap() bug in libc++
-//
-// http://llvm.org/bugs/show_bug.cgi?id=22106
-#if FOLLY_USE_LIBCPP
-    for (size_t i = 0; i < WHEEL_BUCKETS; ++i) {
-      for (size_t ii = 0; ii < WHEEL_SIZE; ++ii) {
-        std::swap(buckets_[i][ii], buckets[i][ii]);
-      }
-    }
-#else
-    std::swap(buckets, buckets_);
-#endif
-
-    for (auto& tick : buckets) {
+    const size_t numElements = WHEEL_BUCKETS * WHEEL_SIZE;
+    size_t maxBuckets = std::min(numElements, count_);
+    auto buckets = folly::make_unique<CallbackList[]>(maxBuckets);
+    size_t countBuckets = 0;
+    for (auto& tick : buckets_) {
       for (auto& bucket : tick) {
-        while (!bucket.empty()) {
-          auto& cb = bucket.front();
-          cb.cancelTimeout();
-          cb.callbackCanceled();
+        if (bucket.empty()) {
+          continue;
+        }
+        for (auto& cb : bucket) {
           count++;
         }
+        std::swap(bucket, buckets[countBuckets++]);
+        if (count >= count_) {
+          break;
+        }
+      }
+    }
+
+    for (size_t i = 0; i < countBuckets; ++i) {
+      auto& bucket = buckets[i];
+      while (!bucket.empty()) {
+        auto& cb = bucket.front();
+        cb.cancelTimeout();
+        cb.callbackCanceled();
       }
     }
   }