diff --git a/src/nsolid/thread_safe.h b/src/nsolid/thread_safe.h index ee97888c0e..55c62c7ed0 100644 --- a/src/nsolid/thread_safe.h +++ b/src/nsolid/thread_safe.h @@ -158,9 +158,17 @@ struct TSList { nsuv::ns_mutex::scoped_lock lock(lock_); std::for_each(list_.begin(), list_.end(), fn); } - inline void erase(iterator it) { + inline void for_each(std::function fn) { + nsuv::ns_mutex::scoped_lock lock(lock_); + size_t current_size = list_.size(); + for (auto& item : list_) { + fn(item, current_size); + } + } + inline size_t erase(iterator it) { nsuv::ns_mutex::scoped_lock lock(lock_); list_.erase(it); + return list_.size(); } inline size_t size() { nsuv::ns_mutex::scoped_lock lock(lock_); @@ -190,9 +198,17 @@ struct TSList { nsuv::ns_mutex::scoped_lock lock(lock_); std::for_each(list_.begin(), list_.end(), fn); } - inline void erase(iterator it) { + inline void for_each(std::function fn) { + nsuv::ns_mutex::scoped_lock lock(lock_); + size_t current_size = list_.size(); + for (auto& item : list_) { + fn(item, current_size); + } + } + inline size_t erase(iterator it) { nsuv::ns_mutex::scoped_lock lock(lock_); list_.erase(it); + return list_.size(); } inline size_t size() { nsuv::ns_mutex::scoped_lock lock(lock_); diff --git a/test/cctest/test_nsolid_thread_safe.cc b/test/cctest/test_nsolid_thread_safe.cc index 364a7ece60..e6091ec9ae 100644 --- a/test/cctest/test_nsolid_thread_safe.cc +++ b/test/cctest/test_nsolid_thread_safe.cc @@ -50,6 +50,86 @@ TEST(TSListTest, ObjectIterator) { }); } +// Test TSList::for_each with size parameter (object specialization) +TEST(TSListTest, ObjectForEachWithSize) { + TSList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + std::vector values; + std::vector sizes; + list.for_each([&](const int& v, size_t size) { + values.push_back(v); + sizes.push_back(size); + }); + EXPECT_EQ(values.size(), 3u); + EXPECT_EQ(sizes[0], 3u); + EXPECT_EQ(sizes[1], 3u); + EXPECT_EQ(sizes[2], 3u); + EXPECT_EQ(values[0], 10); + EXPECT_EQ(values[1], 20); + EXPECT_EQ(values[2], 30); +} + +// Test TSList::erase returns new size (object specialization) +TEST(TSListTest, ObjectEraseReturnsSize) { + TSList list; + auto it1 = list.push_back(1); + auto it2 = list.push_back(2); + auto it3 = list.push_back(3); + EXPECT_EQ(list.erase(it2), 2u); + EXPECT_EQ(list.erase(it1), 1u); + EXPECT_EQ(list.erase(it3), 0u); +} + +// Test TSList::for_each with size parameter (pointer specialization) +TEST(TSListTest, PointerForEachWithSize) { + TSList list; + auto it1 = list.push_back(new int(100)); + auto it2 = list.push_back(new int(200)); + auto it3 = list.push_back(new int(300)); + std::vector values; + std::vector sizes; + list.for_each([&](int* v, size_t size) { + values.push_back(*v); + sizes.push_back(size); + }); + EXPECT_EQ(values.size(), 3u); + EXPECT_EQ(sizes[0], 3u); + EXPECT_EQ(sizes[1], 3u); + EXPECT_EQ(sizes[2], 3u); + EXPECT_EQ(values[0], 100); + EXPECT_EQ(values[1], 200); + EXPECT_EQ(values[2], 300); + // Clean up + int* tmp = *it1; + delete tmp; + tmp = *it2; + delete tmp; + tmp = *it3; + delete tmp; + list.erase(it1); + list.erase(it2); + list.erase(it3); +} + +// Test TSList::erase returns new size (pointer specialization) +TEST(TSListTest, PointerEraseReturnsSize) { + TSList list; + auto it1 = list.push_back(new int(1)); + auto it2 = list.push_back(new int(2)); + auto it3 = list.push_back(new int(3)); + int* p1 = *it1; + int* p2 = *it2; + int* p3 = *it3; + EXPECT_EQ(list.erase(it2), 2u); + EXPECT_EQ(list.erase(it1), 1u); + EXPECT_EQ(list.erase(it3), 0u); + delete p1; + delete p2; + delete p3; +} + TEST(TSListTest, PointerIterator) { TSList list; auto it1 = list.push_back(new int(1));