@@ -316,4 +316,75 @@ TEST(BufferPoolManagerTest, DISABLED_DeadlockTest) {
316
316
child.join ();
317
317
}
318
318
319
+ TEST (BufferPoolManagerTest, DISABLED_EvictableTest) {
320
+ // Test if the evictable status of a frame is always correct.
321
+ size_t rounds = 1000 ;
322
+ size_t num_readers = 8 ;
323
+
324
+ auto disk_manager = std::make_shared<DiskManager>(db_fname);
325
+ // Only allocate 1 frame of memory to the buffer pool manager.
326
+ auto bpm = std::make_shared<BufferPoolManager>(1 , disk_manager.get (), K_DIST);
327
+
328
+ for (size_t i = 0 ; i < rounds; i++) {
329
+ std::mutex mutex;
330
+ std::condition_variable cv;
331
+
332
+ // This signal tells the readers that they can start reading after the main thread has already taken the read latch.
333
+ bool signal = false ;
334
+
335
+ // This page will be loaded into the only available frame.
336
+ page_id_t winner_pid = bpm->NewPage ();
337
+ // We will attempt to load this page into the occupied frame, and it should fail every time.
338
+ page_id_t loser_pid = bpm->NewPage ();
339
+
340
+ std::vector<std::thread> readers;
341
+ for (size_t j = 0 ; j < num_readers; j++) {
342
+ readers.emplace_back ([&]() {
343
+ std::unique_lock<std::mutex> lock (mutex);
344
+
345
+ // Wait until the main thread has taken a read latch on the page.
346
+ while (!signal) {
347
+ cv.wait (lock);
348
+ }
349
+
350
+ // Read the page in shared mode.
351
+ auto read_guard = bpm->ReadPage (winner_pid);
352
+
353
+ // Since the only frame is pinned, no thread should be able to bring in a new page.
354
+ ASSERT_FALSE (bpm->CheckedReadPage (loser_pid).has_value ());
355
+ });
356
+ }
357
+
358
+ std::unique_lock<std::mutex> lock (mutex);
359
+
360
+ if (i % 2 == 0 ) {
361
+ // Take the read latch on the page and pin it.
362
+ auto read_guard = bpm->ReadPage (winner_pid);
363
+
364
+ // Wake up all of the readers.
365
+ signal = true ;
366
+ cv.notify_all ();
367
+ lock.unlock ();
368
+
369
+ // Allow other threads to read.
370
+ read_guard.Drop ();
371
+ } else {
372
+ // Take the read latch on the page and pin it.
373
+ auto write_guard = bpm->WritePage (winner_pid);
374
+
375
+ // Wake up all of the readers.
376
+ signal = true ;
377
+ cv.notify_all ();
378
+ lock.unlock ();
379
+
380
+ // Allow other threads to read.
381
+ write_guard.Drop ();
382
+ }
383
+
384
+ for (size_t i = 0 ; i < num_readers; i++) {
385
+ readers[i].join ();
386
+ }
387
+ }
388
+ }
389
+
319
390
} // namespace bustub
0 commit comments