15. Exception Guarantees
In a low-latency order book, any exception must leave state consistent and quickly recoverable. A misplaced write before a throwing operation can silently degrade correctness under load. Evaluate and fix the guarantees for this hot-path update.
struct Book { std::vector<int> v; bool dirty=false; };
void add(Book& b, int x) {
b.dirty = true;
b.v.push_back(x);
}
Part 1.
What exception-safety guarantee does add currently provide, and how would you minimally change it to provide the strong guarantee? When, if ever, is it correct to make add no-throw?
Part 2.
(1) What guarantee does add provide if push_back throws?
(2) How can reordering operations strengthen guarantees here? Any pitfalls?
(3) When is marking add noexcept correct, and when is it dangerous?
(4) How does pre-reserving capacity impact guarantees and latency?
(5) How would you test exception safety without distorting hot-path performance?
Answer
Answer (Part 1)
As written, add only provides the basic guarantee: resources are intact and Book remains usable, but dirty may be spuriously set. For strong guarantee, commit the observable flag after the potentially-throwing operation:
void add(Book& b, int x) {
b.v.push_back(x);
b.dirty = true;
}
Declare noexcept only when you can prove no allocation (e.g., pre-reserved capacity) and element operations are non-throwing; otherwise noexcept risks std::terminate on rare failures.
Answer (Part 2)
(1) Basic guarantee: no leaks, object valid, but dirty == true despite no append. Not strong, not no-throw.
(2) Perform push_back first, then set dirty to make the change atomic. Ensure any other invariants aren’t partially exposed earlier.
(3) Correct only if you can guarantee no throws (capacity suffices, T moves/copies are noexcept). Dangerous otherwise: it converts failures into termination.
(4) Pre-reserving improves strong/no-throw prospects by avoiding allocations and reduces jitter. The reserve itself can throw and increases memory footprint.
(5) Use fault-injection or a throwing allocator to simulate failures. Benchmark performance separately with exceptions disabled to avoid skew.