folly/fibers/test/FibersTest.cpp: accommodate ASAN's detect_stack_use_after_return=1
[folly.git] / folly / experimental / ReadMostlySharedPtr.h
index 1839b435848a12cd63ae69808d0e221f548a7640..f80fdde1e1aec9e47c25626e5d986ec1cfc71c33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 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.
@@ -28,6 +28,8 @@ template <typename T, typename RefCount>
 class ReadMostlyWeakPtr;
 template <typename T, typename RefCount>
 class ReadMostlySharedPtr;
+template <typename RefCount>
+class ReadMostlyMainPtrDeleter;
 
 using DefaultRefCount = TLRefCount;
 
@@ -79,6 +81,7 @@ class ReadMostlySharedPtrCore {
 
  private:
   friend class ReadMostlyMainPtr<T, RefCount>;
+  friend class ReadMostlyMainPtrDeleter<RefCount>;
 
   explicit ReadMostlySharedPtrCore(std::shared_ptr<T> ptr) :
       ptrRaw_(ptr.get()),
@@ -91,7 +94,7 @@ class ReadMostlySharedPtrCore {
   std::shared_ptr<T> ptr_;
 };
 
-}
+} // namespace detail
 
 template <typename T, typename RefCount = DefaultRefCount>
 class ReadMostlyMainPtr {
@@ -156,9 +159,9 @@ class ReadMostlyMainPtr {
     }
   }
 
-  std::shared_ptr<T> getStdShared() {
+  std::shared_ptr<T> getStdShared() const {
     if (impl_) {
-      return impl_->ptr_;
+      return impl_->getShared();
     } else {
       return {};
     }
@@ -183,6 +186,7 @@ class ReadMostlyMainPtr {
  private:
   friend class ReadMostlyWeakPtr<T, RefCount>;
   friend class ReadMostlySharedPtr<T, RefCount>;
+  friend class ReadMostlyMainPtrDeleter<RefCount>;
 
   detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
 };
@@ -316,7 +320,7 @@ class ReadMostlySharedPtr {
 
   std::shared_ptr<T> getStdShared() const {
     if (impl_) {
-      return impl_->ptr_;
+      return impl_->getShared();
     } else {
       return {};
     }
@@ -362,4 +366,89 @@ class ReadMostlySharedPtr {
   detail::ReadMostlySharedPtrCore<T, RefCount>* impl_{nullptr};
 };
 
+/**
+ * This can be used to destroy multiple ReadMostlyMainPtrs at once.
+ */
+template <typename RefCount = DefaultRefCount>
+class ReadMostlyMainPtrDeleter {
+ public:
+  ~ReadMostlyMainPtrDeleter() noexcept {
+    RefCount::useGlobal(refCounts_);
+    for (auto& decref : decrefs_) {
+      decref();
+    }
+  }
+
+  template <typename T>
+  void add(ReadMostlyMainPtr<T, RefCount> ptr) noexcept {
+    if (!ptr.impl_) {
+      return;
+    }
+
+    refCounts_.push_back(&ptr.impl_->count_);
+    refCounts_.push_back(&ptr.impl_->weakCount_);
+    decrefs_.push_back([impl = ptr.impl_] { impl->decref(); });
+    ptr.impl_ = nullptr;
+  }
+
+ private:
+  std::vector<RefCount*> refCounts_;
+  std::vector<folly::Function<void()>> decrefs_;
+};
+
+template <typename T, typename RefCount>
+inline bool operator==(
+    const ReadMostlyMainPtr<T, RefCount>& ptr,
+    std::nullptr_t) {
+  return ptr.get() == nullptr;
+}
+
+template <typename T, typename RefCount>
+inline bool operator==(
+    std::nullptr_t,
+    const ReadMostlyMainPtr<T, RefCount>& ptr) {
+  return ptr.get() == nullptr;
+}
+
+template <typename T, typename RefCount>
+inline bool operator==(
+    const ReadMostlySharedPtr<T, RefCount>& ptr,
+    std::nullptr_t) {
+  return ptr.get() == nullptr;
+}
+
+template <typename T, typename RefCount>
+inline bool operator==(
+    std::nullptr_t,
+    const ReadMostlySharedPtr<T, RefCount>& ptr) {
+  return ptr.get() == nullptr;
+}
+
+template <typename T, typename RefCount>
+inline bool operator!=(
+    const ReadMostlyMainPtr<T, RefCount>& ptr,
+    std::nullptr_t) {
+  return !(ptr == nullptr);
+}
+
+template <typename T, typename RefCount>
+inline bool operator!=(
+    std::nullptr_t,
+    const ReadMostlyMainPtr<T, RefCount>& ptr) {
+  return !(ptr == nullptr);
+}
+
+template <typename T, typename RefCount>
+inline bool operator!=(
+    const ReadMostlySharedPtr<T, RefCount>& ptr,
+    std::nullptr_t) {
+  return !(ptr == nullptr);
+}
+
+template <typename T, typename RefCount>
+inline bool operator!=(
+    std::nullptr_t,
+    const ReadMostlySharedPtr<T, RefCount>& ptr) {
+  return !(ptr == nullptr);
 }
+} // namespace folly