@@ -276,4 +276,44 @@ TEST(BufferPoolManagerTest, DISABLED_ContentionTest) {
276
276
thread1.join ();
277
277
}
278
278
279
+ TEST (BufferPoolManagerTest, DISABLED_DeadlockTest) {
280
+ auto disk_manager = std::make_shared<DiskManager>(db_fname);
281
+ auto bpm = std::make_shared<BufferPoolManager>(FRAMES, disk_manager.get (), K_DIST);
282
+
283
+ auto pid0 = bpm->NewPage ();
284
+ auto pid1 = bpm->NewPage ();
285
+
286
+ auto guard0 = bpm->WritePage (pid0);
287
+
288
+ // A crude way of synchronizing threads, but works for this small case.
289
+ std::atomic<bool > start = false ;
290
+
291
+ auto child = std::thread ([&]() {
292
+ // Acknowledge that we can begin the test.
293
+ start.store (true );
294
+
295
+ // Attempt to write to page 0.
296
+ auto guard0 = bpm->WritePage (pid0);
297
+ });
298
+
299
+ // Wait for the other thread to begin before we start the test.
300
+ while (!start.load ()) {
301
+ }
302
+
303
+ // Make the other thread wait for a bit.
304
+ // This mimics the main thread doing some work while holding the write latch on page 0.
305
+ std::this_thread::sleep_for (std::chrono::milliseconds (1000 ));
306
+
307
+ // If your latching mechanism is incorrect, the next line of code will deadlock.
308
+ // Think about what might happen if you hold a certain "all-encompassing" latch for too long...
309
+
310
+ // While holding page 0, take the latch on page 1.
311
+ auto guard1 = bpm->WritePage (pid1);
312
+
313
+ // Let the child thread have the page 0 since we're done with it.
314
+ guard0.Drop ();
315
+
316
+ child.join ();
317
+ }
318
+
279
319
} // namespace bustub
0 commit comments