Select Features and Configuration
Deloxide’s features are Cargo compile-time choices, not runtime switches. Start
with the default active wait-for detector, then add only the evidence or test
behavior needed for the environment. The public base API is always
Deloxide,
Mutex,
RwLock,
Condvar,
DeadlockInfo,
and thread.
| Build | Additional API enabled | Runtime work added | Intended environment | Complete Cargo.toml dependency |
|---|---|---|---|---|
| Default | Base API only | Active wait-for tracking for supported, tracked primitives; callbacks on findings. | Reproductions and measured normal deployments. | deloxide = "1.1.0" |
logging-and-visualization | Deloxide::with_log, no_logging, showcase, and showcase_this. | Event queue, serialization, asynchronous log writer, and file I/O. | Incident capture and local investigation. | deloxide = { version = "1.1.0", features = ["logging-and-visualization"] } |
lock-order-graph | with_lock_order_checking and no_lock_order_checking. | Historical lock-order edges and cycle checks in addition to active tracking. | Development and CI. | deloxide = { version = "1.1.0", features = ["lock-order-graph"] } |
stress-test | StressConfig, StressMode, with_random_stress, with_component_stress, and with_stress_config. | Configured delays/preemption behavior around lock attempts; slower, less deterministic execution. | Focused tests and reproductions only. | deloxide = { version = "1.1.0", features = ["stress-test"] } |
| All optional features | All APIs above. | Logging, historical order tracking, and optional stress behavior when selected by the builder. | Comprehensive local/CI diagnosis, after measuring the combined cost. | deloxide = { version = "1.1.0", features = ["logging-and-visualization", "lock-order-graph", "stress-test"] } |
Use one dependency line in the application’s Cargo.toml; the cells above are
complete alternatives, not lines to combine.
Builder defaults follow compiled features
Deloxide::new
always supplies a callback that panics with the report unless you replace it with
callback.
When logging-and-visualization is compiled, it enables logging by default with
the path deloxide.log; change that path with with_log, or disable logging for
the initial configuration with no_logging. When lock-order-graph is compiled,
lock-order checking is enabled by default; make the initial policy explicit with
with_lock_order_checking, or use no_lock_order_checking for a controlled
baseline. Stress compilation alone does not add delays: select random or
component stress with its corresponding builder method.
#![allow(unused)]
fn main() {
extern crate deloxide;
#[cfg(feature = "logging-and-visualization")]
{
use deloxide::Deloxide;
Deloxide::new()
.with_log("logs/deloxide_{timestamp}.log")
.callback(|report| eprintln!("{report:?}"))
.start()
.expect("logging detector initialization");
}
#[cfg(not(feature = "logging-and-visualization"))]
{
let _ = "this configuration needs the logging-and-visualization feature";
}
}
#![allow(unused)]
fn main() {
extern crate deloxide;
#[cfg(feature = "lock-order-graph")]
{
use deloxide::{DeadlockSource, Deloxide};
Deloxide::new()
.with_lock_order_checking()
.callback(|report| match report.source {
DeadlockSource::WaitForGraph => eprintln!("active cycle"),
DeadlockSource::LockOrderViolation => eprintln!("potential order cycle"),
})
.start()
.expect("order-checking detector initialization");
}
#[cfg(not(feature = "lock-order-graph"))]
{
let _ = "this configuration needs the lock-order-graph feature";
}
}
Both builder calls are feature-gated at compile time. Do not put them behind only
a runtime if: a binary built without the feature has no such methods.
Choose the evidence level deliberately
The lock-order-graph feature can report
DeadlockSource::LockOrderViolation
when observed acquisitions close a historical order cycle. It is useful early in
development, but it is not evidence that threads are blocked now. The base
wait-for detector’s
DeadlockSource::WaitForGraph
is the active, validated-cycle finding. Keep those response paths distinct even
when all features are compiled.
Stress mode changes scheduling to make a suspected bug easier to reproduce; it does not turn a potential order warning into a confirmed deadlock. Logging adds history for the supported events it receives, not a complete trace of every thread and primitive in the process. See Choosing a Mode for operational trade-offs, Finding Inconsistent Lock Order for potential findings, and Stress Test a Suspected Race for test-only stress workflows.
Cargo features are fixed when the application is built. Choose one runtime
builder configuration and start it before instrumented work. Repeated start()
calls are accepted, but their effects are asymmetric: the first successfully
installed callback and global logger win; an enabled lock-order graph is created
or replaced, while a later disabled setting does not remove an existing graph;
and stress mode/configuration is overwritten on each start. Existing ownership
and wait state is not reset coherently with those changes. Repeated starts are
therefore partial, unsupported reconfiguration, not a reliable reset or toggle.
Use separate processes for clean configurations; see Manage Lifecycle and
Callbacks for the exact behavior.