@@ -45,7 +45,11 @@ class SVSThreadPoolTest : public ::testing::Test {
4545 saved_callback_ = VecSimIndexInterface::logCallback;
4646 VecSimIndexInterface::logCallback = nullptr ;
4747 }
48- void TearDown () override { VecSimIndexInterface::logCallback = saved_callback_; }
48+ void TearDown () override {
49+ // Reset the shared singleton pool to size 1 so tests don't leak state.
50+ VecSimSVSThreadPool::resize (1 );
51+ VecSimIndexInterface::logCallback = saved_callback_;
52+ }
4953
5054private:
5155 logCallbackFunction saved_callback_ = nullptr ;
@@ -55,7 +59,7 @@ class SVSThreadPoolTest : public ::testing::Test {
5559// Test 1: VecSimSVSThreadPoolImpl::resize — grow and shrink
5660// ---------------------------------------------------------------------------
5761TEST_F (SVSThreadPoolTest, ResizeGrowAndShrink) {
58- auto pool = std::make_shared<VecSimSVSThreadPoolImpl>( 1 );
62+ auto pool = VecSimSVSThreadPoolImpl::instance ( );
5963 ASSERT_EQ (pool->size (), 1 );
6064
6165 // Grow 1 → 4
@@ -91,11 +95,12 @@ TEST_F(SVSThreadPoolTest, ResizeGrowAndShrink) {
9195// ---------------------------------------------------------------------------
9296TEST_F (SVSThreadPoolTest, ShrinkWhileRented) {
9397 // Pool size 5: 4 worker slots [s0, s1, s2, s3].
94- auto pool = std::make_shared<VecSimSVSThreadPoolImpl>(5 );
98+ auto pool = VecSimSVSThreadPoolImpl::instance ();
99+ pool->resize (5 );
95100 ASSERT_EQ (pool->size (), 5 );
96101
97102 // Wrapper A uses parallelism 3 → rents 2 workers (s0, s1).
98- VecSimSVSThreadPool wrapperA (pool) ;
103+ VecSimSVSThreadPool wrapperA;
99104 wrapperA.setParallelism (3 );
100105
101106 std::latch hold (1 ); // blocks rented workers
@@ -133,7 +138,7 @@ TEST_F(SVSThreadPoolTest, ShrinkWhileRented) {
133138
134139 // While wrapperA's threads are still alive (blocked on latch), run
135140 // parallel_for on the shrunk pool with a second wrapper using a free slot.
136- VecSimSVSThreadPool wrapperB (pool) ;
141+ VecSimSVSThreadPool wrapperB;
137142 // Parallelism 2 = 1 rented worker + calling thread. The pool has 3 slots
138143 // [s0, s1, s2] after shrink; s0 and s1 are occupied by wrapperA, so the
139144 // single rented worker will get s2 (the only free slot).
@@ -158,11 +163,12 @@ TEST_F(SVSThreadPoolTest, ShrinkWhileRented) {
158163// ---------------------------------------------------------------------------
159164TEST_F (SVSThreadPoolTest, GrowWhileRented) {
160165 // Pool size 3: 2 worker slots [s0, s1].
161- auto pool = std::make_shared<VecSimSVSThreadPoolImpl>(3 );
166+ auto pool = VecSimSVSThreadPoolImpl::instance ();
167+ pool->resize (3 );
162168 ASSERT_EQ (pool->size (), 3 );
163169
164170 // Wrapper A uses parallelism 3 → rents 2 workers (s0, s1).
165- VecSimSVSThreadPool wrapperA (pool) ;
171+ VecSimSVSThreadPool wrapperA;
166172 wrapperA.setParallelism (3 );
167173
168174 std::latch hold (1 ); // blocks rented workers
@@ -198,7 +204,7 @@ TEST_F(SVSThreadPoolTest, GrowWhileRented) {
198204 // Wrapper B uses parallelism 3 → rents 2 workers. s0, s1 are occupied by
199205 // wrapperA, so it gets the 2 newly created slots s2, s3... but we only
200206 // need 2 of the 3 free slots (s2, s3 are free, only need 2).
201- VecSimSVSThreadPool wrapperB (pool) ;
207+ VecSimSVSThreadPool wrapperB;
202208 wrapperB.setParallelism (3 );
203209 std::atomic_int resultB{0 };
204210 wrapperB.parallel_for ([&](size_t ) { resultB++; }, 3 );
@@ -227,9 +233,9 @@ TEST_F(SVSThreadPoolTest, GrowWhileRented) {
227233// the original is visible to SVS's copy when it calls size().
228234// ---------------------------------------------------------------------------
229235TEST_F (SVSThreadPoolTest, ParallelismPropagationAcrossCopies) {
230- auto pool = std::make_shared<VecSimSVSThreadPoolImpl> (8 );
236+ VecSimSVSThreadPool::resize (8 );
231237
232- VecSimSVSThreadPool original (pool) ;
238+ VecSimSVSThreadPool original;
233239 original.setParallelism (2 );
234240 ASSERT_EQ (original.size (), 2 );
235241
@@ -259,10 +265,10 @@ TEST_F(SVSThreadPoolTest, ParallelismPropagationAcrossCopies) {
259265// sequentially using disjoint thread budgets.
260266// ---------------------------------------------------------------------------
261267TEST_F (SVSThreadPoolTest, TwoIndexesIndependentParallelism) {
262- auto pool = std::make_shared<VecSimSVSThreadPoolImpl> (8 );
268+ VecSimSVSThreadPool::resize (8 );
263269
264- VecSimSVSThreadPool wrapperA (pool) ;
265- VecSimSVSThreadPool wrapperB (pool) ;
270+ VecSimSVSThreadPool wrapperA;
271+ VecSimSVSThreadPool wrapperB;
266272
267273 wrapperA.setParallelism (2 );
268274 wrapperB.setParallelism (5 );
@@ -306,7 +312,7 @@ TEST_F(SVSThreadPoolTest, TwoIndexesIndependentParallelism) {
306312// The C API sets write mode and resizes the shared singleton pool.
307313// ---------------------------------------------------------------------------
308314TEST_F (SVSThreadPoolTest, UpdateThreadPoolSizeModeTransitions) {
309- auto pool = SVSIndexBase::getSharedThreadPool ();
315+ auto pool = VecSimSVSThreadPoolImpl::instance ();
310316
311317 // 0 → 4: switch to async mode, pool resizes to 4.
312318 VecSim_UpdateThreadPoolSize (4 );
@@ -345,11 +351,11 @@ TEST_F(SVSThreadPoolTest, UpdateThreadPoolSizeModeTransitions) {
345351// ---------------------------------------------------------------------------
346352TEST_F (SVSThreadPoolTest, ConcurrentRentalFromTwoIndexes) {
347353 // Pool size 8: wrappers A (4) and B (4) sum to exactly 8.
348- auto pool = std::make_shared<VecSimSVSThreadPoolImpl> (8 );
354+ VecSimSVSThreadPool::resize (8 );
349355
350- VecSimSVSThreadPool wrapperA (pool) ;
356+ VecSimSVSThreadPool wrapperA;
351357 wrapperA.setParallelism (4 );
352- VecSimSVSThreadPool wrapperB (pool) ;
358+ VecSimSVSThreadPool wrapperB;
353359 wrapperB.setParallelism (4 );
354360
355361 std::atomic_int resultA{0 };
@@ -398,7 +404,7 @@ TEST_F(SVSThreadPoolTest, ConcurrentRentalFromTwoIndexes) {
398404 << " Timed out waiting for concurrent parallel_for calls. "
399405 " resultA="
400406 << resultA << " , resultB=" << resultB << " , idsA.size=" << idsA.size ()
401- << " , idsB.size=" << idsB.size () << " , pool_size=" << pool-> size ();
407+ << " , idsB.size=" << idsB.size () << " , pool_size=" << wrapperA. poolSize ();
402408
403409 ASSERT_EQ (resultA, 4 );
404410 ASSERT_EQ (resultB, 4 );
@@ -424,9 +430,9 @@ TEST_F(SVSThreadPoolTest, ConcurrentRentalFromTwoIndexes) {
424430// ---------------------------------------------------------------------------
425431TEST_F (SVSThreadPoolTest, AllThreadsOccupied) {
426432 // Pool size 4 (3 worker slots). Wrapper A rents all 3.
427- auto pool = std::make_shared<VecSimSVSThreadPoolImpl> (4 );
433+ VecSimSVSThreadPool::resize (4 );
428434
429- VecSimSVSThreadPool wrapperA (pool) ;
435+ VecSimSVSThreadPool wrapperA;
430436 wrapperA.setParallelism (4 );
431437
432438 std::latch hold (1 );
@@ -449,10 +455,10 @@ TEST_F(SVSThreadPoolTest, AllThreadsOccupied) {
449455 ASSERT_TRUE (wait_with_timeout (workers_ready, kTestTimeout ))
450456 << " Timed out waiting for wrapper A's 3 workers to start. "
451457 " resultA="
452- << resultA << " , pool_size=" << pool-> size ();
458+ << resultA << " , pool_size=" << wrapperA. poolSize ();
453459
454460 // All 3 worker slots are occupied. Wrapper B tries to rent 1 worker.
455- VecSimSVSThreadPool wrapperB (pool) ;
461+ VecSimSVSThreadPool wrapperB;
456462 wrapperB.setParallelism (2 );
457463
458464#ifdef NDEBUG
0 commit comments