/*
- * Copyright 2013 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 <time.h>
+#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, milliseconds) \
- for (bool LOG_EVERY_MS_once = true; LOG_EVERY_MS_once; ) \
- for (const ::clock_t LOG_EVERY_MS_now = ::clock(); LOG_EVERY_MS_once; ) \
- for (static ::clock_t LOG_EVERY_MS_last; LOG_EVERY_MS_once; \
- LOG_EVERY_MS_once = false) \
- if (1000 * (LOG_EVERY_MS_now - LOG_EVERY_MS_last) < \
- (milliseconds) * CLOCKS_PER_SEC) {} \
- else \
- (LOG_EVERY_MS_last = LOG_EVERY_MS_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_