logging: implement FATAL and DFATAL log levels
[folly.git] / folly / AtomicLinkedList.h
index ee826a7b00d439755a95b4c13f924b3e56588543..4d1d8503452ad6683be6a8fc479a4f343bf16d9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#pragma once
 
-#include <atomic>
-#include <cassert>
+#pragma once
 
 #include <folly/AtomicIntrusiveLinkedList.h>
 #include <folly/Memory.h>
@@ -46,7 +44,9 @@ class AtomicLinkedList {
     sweep([](T&&) {});
   }
 
-  bool empty() const { return list_.empty(); }
+  bool empty() const {
+    return list_.empty();
+  }
 
   /**
    * Atomically insert t at the head of the list.
@@ -54,7 +54,7 @@ class AtomicLinkedList {
    *         after the call.
    */
   bool insertHead(T t) {
-    auto wrapper = folly::make_unique<Wrapper>(std::move(t));
+    auto wrapper = std::make_unique<Wrapper>(std::move(t));
 
     return list_.insertHead(wrapper.release());
   }
@@ -73,6 +73,28 @@ class AtomicLinkedList {
     });
   }
 
+  /**
+   * Similar to sweep() but calls func() on elements in LIFO order.
+   *
+   * func() is called for all elements in the list at the moment
+   * reverseSweep() is called.  Unlike sweep() it does not loop to ensure the
+   * list is empty at some point after the last invocation.  This way callers
+   * can reason about the ordering: elements inserted since the last call to
+   * reverseSweep() will be provided in LIFO order.
+   *
+   * Example: if elements are inserted in the order 1-2-3, the callback is
+   * invoked 3-2-1.  If the callback moves elements onto a stack, popping off
+   * the stack will produce the original insertion order 1-2-3.
+   */
+  template <typename F>
+  void reverseSweep(F&& func) {
+    list_.reverseSweep([&](Wrapper* wrapperPtr) mutable {
+      std::unique_ptr<Wrapper> wrapper(wrapperPtr);
+
+      func(std::move(wrapper->data));
+    });
+  }
+
  private:
   struct Wrapper {
     explicit Wrapper(T&& t) : data(std::move(t)) {}