00_README.md

šŸ” Juspay Part B — Thread-Safe Tree of Space: Complete Code & Concepts

This folder contains every thread-safe approach you can write for the Tree of Space problem. Each file covers one mechanism in depth: what it is, how it works internally, when to use it, and complete working code.


šŸ“‚ File Index

#FileWhat It Covers
101_mutex_explained.mdWhat is a Mutex? Internals (futex, CMPXCHG, kernel sleep). Global mutex → Per-node mutex. Full code.
202_custom_mutex_spinlock.mdBuild your own Mutex using __sync_lock_test_and_set (TAS) and CAS. Ownership Mutex. Full code.
303_atomic_operations.mdstd::atomic<int>, AtomicInteger, CAS lock-free approach. compare_exchange_strong. Full code.
404_synchronized_keyword.mdJava synchronized keyword. Monitor locks. ReentrantLock. How JVM implements it. Full code.
505_semaphores.mdBinary vs Counting Semaphore. Internals. Why counting semaphore CANNOT work here. Full code.
606_set_vs_count_optimal.mdā˜… THE TWO OPTIMAL SOLUTIONS COMPARED ā˜… — set<Node*> lockedDescendants vs int lockedDescCount. Time complexity, upgrade differences, which is truly optimal.
707_software_algorithms.mdPeterson's Algorithm, Lamport's Bakery, Set-and-Test pattern. No hardware atomics at all.
808_custom_scheduler.mdThe "no synchronization primitives" approach: sibling scheduling. From your Attempt3 Java code.
909_read_write_locks.mdshared_mutex, shared_lock vs unique_lock. Read-write separation for ancestors.
1010_interview_cheatsheet.mdQuick-reference: what to say at each stage, race conditions summary, traces.

šŸŽÆ Quick Decision Tree: Which Approach When?

Interviewer: "Make lock() thread-safe" │ ā”œā”€ "Use any tool" ─────────────► std::mutex (per-node) [File 01] │ or std::atomic CAS [File 03] │ ā”œā”€ "No std::mutex allowed" ────► Custom spinlock via __sync_* [File 02] │ or std::atomic CAS [File 03] │ ā”œā”€ "No atomics either" ────────► Peterson's / Bakery Algorithm [File 07] │ or Set-and-Test pattern [File 07] │ └─ "No primitives at all" ─────► Custom Thread Scheduler [File 08] (sibling isolation)

⚔ The Two Optimal Part A Solutions (Critical Distinction)

ApproachDescendant CheckUpgrade ComplexitySpace
set<Node*> lockedDescendantsO(1) — set.empty()O(K Ɨ log_M N) — iterate set, unlock eachO(N)
int lockedDescCountO(1) — count > 0O(N) — must BFS subtree to FIND which nodes are lockedO(N)

The set approach is the truly optimal one. The count approach has O(1) descendant check but O(N) upgrade because you lose track of which descendants are locked.

See File 06 for the full comparison.