| ## C++ Best Practices |
| |
| ### State Machine for Asynchronous Queries |
| |
| When dealing with asynchronous D-Bus queries that can be triggered by external |
| events (like `InterfacesAdded`), use a state machine to handle race conditions |
| and defer events: |
| |
| - Use a `querying` boolean flag to protect the critical section during an active |
| query. |
| - Use an enum state (e.g., `None`, `Add`, `Remove`) to record events that arrive |
| _while_ a query is in flight. |
| - When the query completes, check the recorded state and trigger a deferred |
| query if needed (e.g., if an `Add` event arrived). |
| - Centralize the setting and clearing of the `querying` flag inside the query |
| function to avoid scattered state management. |
| |
| ### Compare, Don't Subtract for Sentinel Time Points |
| |
| Because of the guaranteed overflow, you should never perform arithmetic |
| operations on `time_point::min()` or `time_point::max()`. They are strictly |
| meant to be used as sentinel (flag) values. |
| |
| If you need to know if an interval is valid, use equality operators (`==` or |
| `!=`) to check the state of the variable before doing any math: |
| |
| ```cpp |
| auto last_event = std::chrono::steady_clock::time_point::min(); |
| auto current_time = std::chrono::steady_clock::now(); |
| |
| // ❌ WRONG: This will overflow and cause undefined behavior! |
| // auto elapsed = current_time - last_event; |
| |
| // ✅ CORRECT: Check the sentinel value first |
| if (last_event != std::chrono::steady_clock::time_point::min()) { |
| auto elapsed = current_time - last_event; |
| // Process the elapsed time... |
| } |
| |
| ## Testing & Debugging |
| |
| ### Verify Mock Before Questioning Infrastructure |
| Before questioning Object Mapper (mapperx) performance or behavior in a testing environment, use `dbus-monitor` and `busctl` to examine the mock server implementation. The mock might be static or missing dynamic behaviors expected by the test. |
| |
| ### Use A/B Testing for Regressions |
| Use A/B testing (running specific tests with and without your changes) to narrow down which change broke what test, before claiming the test was already failing before your changes. |
| ``` |