Add a check if max atomic_shared_ptrs is reached.
authorDave Watson <davejwatson@fb.com>
Tue, 9 Jan 2018 15:30:49 +0000 (07:30 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 9 Jan 2018 15:35:44 +0000 (07:35 -0800)
Summary:
Batching reference counts reduces the maximum number of atomic_shared_ptrs
available to the system (and also shared_ptrs).

Add a check, test, and some comments about it.

Reviewed By: yfeldblum

Differential Revision: D5916291

fbshipit-source-id: 0bbf7b43284d94a304201219883c82b3654c1585

folly/concurrency/detail/AtomicSharedPtr-detail.h
folly/concurrency/test/AtomicSharedPtrTest.cpp

index 02d8be0..90d6835 100644 (file)
 #include <atomic>
 #include <memory>
 
+#include <folly/lang/SafeAssert.h>
+
 namespace folly {
 namespace detail {
 
+// This implementation is specific to libstdc++, now accepting
+// diffs for other libraries.
+
+// Specifically, this adds support for two things:
+// 1) incrementing/decrementing the shared count by more than 1 at a time
+// 2) Getting the thing the shared_ptr points to, which may be different from
+//    the aliased pointer.
+
 class shared_ptr_internals {
  public:
   template <typename T, typename... Args>
@@ -42,6 +52,11 @@ class shared_ptr_internals {
   }
 
   static void inc_shared_count(counted_base* base, long count) {
+    // Check that we don't exceed the maximum number of atomic_shared_ptrs.
+    // Consider setting EXTERNAL_COUNT lower if this CHECK is hit.
+    FOLLY_SAFE_CHECK(
+        base->_M_get_use_count() + count < INT_MAX,
+        "atomic_shared_ptr overflow");
     __gnu_cxx::__atomic_add_dispatch(
         &(base->*fieldPtr(access_use_count{})), count);
   }
index aa8c543..410e743 100644 (file)
@@ -145,6 +145,17 @@ TEST(AtomicSharedPtr, AliasingConstructorTest) {
   EXPECT_EQ(2, d_count);
 }
 
+TEST(AtomicSharedPtr, MaxPtrs) {
+  shared_ptr<long> p(new long);
+  int max_atomic_shared_ptrs = 262144;
+  atomic_shared_ptr<long> ptrs[max_atomic_shared_ptrs];
+  for (int i = 0; i < max_atomic_shared_ptrs - 1; i++) {
+    ptrs[i].store(p);
+  }
+  atomic_shared_ptr<long> fail;
+  EXPECT_DEATH(fail.store(p), "");
+}
+
 TEST(AtomicSharedPtr, DeterministicTest) {
   DSched sched(DSched::uniform(FLAGS_seed));