Fix another race in Notification Queue
[folly.git] / folly / ProducerConsumerQueue.h
index d5d41aaf8dbeae57e7958ddebe49af3581edf484..ff1a4fe13b3dbe35903c4adf5dee3ac0a85f10d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 #include <type_traits>
 #include <utility>
 #include <boost/noncopyable.hpp>
+#include <boost/type_traits.hpp>
 
 namespace folly {
 
@@ -59,7 +60,7 @@ struct ProducerConsumerQueue : private boost::noncopyable {
     // We need to destruct anything that may still exist in our queue.
     // (No real synchronization needed at destructor time: only one
     // thread can be doing this.)
-    if (!std::has_trivial_destructor<T>::value) {
+    if (!boost::has_trivial_destructor<T>::value) {
       int read = readIndex_;
       int end = writeIndex_;
       while (read != end) {
@@ -149,6 +150,20 @@ struct ProducerConsumerQueue : private boost::noncopyable {
     return true;
   }
 
+  // * If called by consumer, then true size may be more (because producer may
+  //   be adding items concurrently).
+  // * If called by producer, then true size may be less (because consumer may
+  //   be removing items concurrently).
+  // * It is undefined to call this from any other thread.
+  size_t sizeGuess() const {
+    int ret = writeIndex_.load(std::memory_order_consume) -
+              readIndex_.load(std::memory_order_consume);
+    if (ret < 0) {
+      ret += size_;
+    }
+    return ret;
+  }
+
 private:
   const uint32_t size_;
   T* const records_;