+struct NonTrivialValue {
+ static std::atomic<int> InstanceCounter;
+ static const int kBadPayLoad;
+
+ NonTrivialValue() : payload_(kBadPayLoad) { ++InstanceCounter; }
+
+ explicit NonTrivialValue(int payload) : payload_(payload) {
+ ++InstanceCounter;
+ }
+
+ NonTrivialValue(const NonTrivialValue& rhs) : payload_(rhs.payload_) {
+ ++InstanceCounter;
+ }
+
+ NonTrivialValue& operator=(const NonTrivialValue& rhs) {
+ payload_ = rhs.payload_;
+ return *this;
+ }
+
+ ~NonTrivialValue() { --InstanceCounter; }
+
+ bool operator<(const NonTrivialValue& rhs) const {
+ EXPECT_NE(kBadPayLoad, payload_);
+ EXPECT_NE(kBadPayLoad, rhs.payload_);
+ return payload_ < rhs.payload_;
+ }
+
+ private:
+ int payload_;
+};
+
+std::atomic<int> NonTrivialValue::InstanceCounter(0);
+const int NonTrivialValue::kBadPayLoad = 0xDEADBEEF;
+
+template <typename SkipListPtrType>
+void TestNonTrivialDeallocation(SkipListPtrType& list) {
+ {
+ auto accessor = typename SkipListPtrType::element_type::Accessor(list);
+ static const size_t N = 10000;
+ for (size_t i = 0; i < N; ++i) {
+ accessor.add(NonTrivialValue(i));
+ }
+ list.reset();
+ }
+ EXPECT_EQ(0, NonTrivialValue::InstanceCounter);
+}
+
+template <typename ParentAlloc>
+void NonTrivialDeallocationWithParanoid() {
+ using Alloc = ParanoidArenaAlloc<ParentAlloc>;
+ using ParanoidSkipListType =
+ ConcurrentSkipList<NonTrivialValue, std::less<NonTrivialValue>, Alloc>;
+ ParentAlloc parentAlloc;
+ Alloc paranoidAlloc(&parentAlloc);
+ auto list = ParanoidSkipListType::createInstance(10, paranoidAlloc);
+ TestNonTrivialDeallocation(list);
+ EXPECT_TRUE(paranoidAlloc.isEmpty());
+}
+
+TEST(ConcurrentSkipList, NonTrivialDeallocationWithParanoidSysAlloc) {
+ NonTrivialDeallocationWithParanoid<SysAlloc>();
+}
+
+TEST(ConcurrentSkipList, NonTrivialDeallocationWithParanoidSysArena) {
+ NonTrivialDeallocationWithParanoid<SysArena>();
+}
+
+TEST(ConcurrentSkipList, NonTrivialDeallocationWithSysArena) {
+ using SysArenaSkipListType =
+ ConcurrentSkipList<NonTrivialValue, std::less<NonTrivialValue>, SysArena>;
+ auto list = SysArenaSkipListType::createInstance(10);
+ TestNonTrivialDeallocation(list);
+}
+