Use simpler tags for ctor dispatch in exception_wrapper
[folly.git] / folly / Logging.h
index 488132b98eaeba92e2d6258195c18fa9982d6314..106aec3a94feff38eb7a3b439138a1a7cb112d23 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 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.
  * limitations under the License.
  */
 
-#ifndef FOLLY_LOGGING_H_
-#define FOLLY_LOGGING_H_
+#pragma once
 
+#include <atomic>
 #include <chrono>
+
 #include <glog/logging.h>
 
 #ifndef FB_LOG_EVERY_MS
  *   " since you last saw this.";
  *
  * The implementation uses for statements to introduce variables in
- * a nice way that doesn't mess surrounding statements.
+ * a nice way that doesn't mess surrounding statements.  It is thread
+ * safe.  Non-positive intervals will always log.
  */
-#define FB_LOG_EVERY_MS(severity, milli_interval)                       \
-  for (bool FB_LEM_once = true; FB_LEM_once; )                          \
-    for (const auto FB_LEM_now = ::std::chrono::system_clock::now();    \
-         FB_LEM_once; )                                                 \
-      for (static ::std::chrono::system_clock::time_point FB_LEM_last;  \
-            FB_LEM_once; FB_LEM_once = false)                           \
-        if (FB_LEM_now - FB_LEM_last <                                  \
-            ::std::chrono::milliseconds(milli_interval)) {              \
-        } else                                                          \
-          (FB_LEM_last = FB_LEM_now, LOG(severity))
+#define FB_LOG_EVERY_MS(severity, milli_interval)                            \
+  for (decltype(milli_interval) FB_LEM_once = 1,                             \
+                                FB_LEM_interval = (milli_interval);          \
+       FB_LEM_once; )                                                        \
+    for (::std::chrono::milliseconds::rep FB_LEM_prev, FB_LEM_now =          \
+             FB_LEM_interval <= 0 ? 0 :                                      \
+             ::std::chrono::duration_cast< ::std::chrono::milliseconds>(     \
+                 ::std::chrono::system_clock::now().time_since_epoch()       \
+                 ).count();                                                  \
+         FB_LEM_once; )                                                      \
+      for (static ::std::atomic< ::std::chrono::milliseconds::rep>           \
+               FB_LEM_hist; FB_LEM_once; FB_LEM_once = 0)                    \
+        if (FB_LEM_interval > 0 &&                                           \
+            (FB_LEM_now - (FB_LEM_prev =                                     \
+                           FB_LEM_hist.load(std::memory_order_acquire)) <    \
+                                                          FB_LEM_interval || \
+             !FB_LEM_hist.compare_exchange_strong(FB_LEM_prev,FB_LEM_now))) {\
+        } else                                                               \
+          LOG(severity)
 
 #endif
-
-#endif  // FOLLY_LOGGING_H_