Struct topo::CallId[][src]

pub struct CallId { /* fields omitted */ }
Expand description

Identifies the scope of a nested function call in a way that can be deterministically reproduced across multiple executions.

The CallId::current for a function call is the combined product of:

  • a callsite: the std::panic::Location where the function was called
  • a parent: the CallId::current which was active when calling the function
  • a slot: a value indicating the call’s “index” within the parent call

When a nested call returns or unwinds, it reverts CallId::current to the parent CallId.

Example

use topo::{call, root, CallId};

let returns_two_ids = || {
    let first = call(|| CallId::current());
    let second = call(|| CallId::current());
    assert_ne!(first, second, "these are always distinct calls");
    (first, second)
};

// running the closure as a nested call(...) gives different siblings
assert_ne!(call(returns_two_ids), call(returns_two_ids));

// a call to root(...) gives each of these closure calls an identical parent CallId
assert_eq!(root(returns_two_ids), root(returns_two_ids));

Creation

Every CallId is created by calling one of:

Slots

Slots are used to differentiate between repeated calls at the same callsite and define the “index” of a child call within its parent. By default (and in call) the slot is populated by the number of times the current callsite has been called in this parent. Users can provide their own slot with call_in_slot or using #[topo::nested(slot = "...")]:

See call_in_slot and nested for examples.

Roots

The topmost parent or “root” of a callgraph can be defined in two ways:

  1. a call or call_in_slot invocation with no parent implicitly creates its own root
  2. an explicit call to root creates a new subgraph regardless of the current parent

See root for examples.

CallId and multiple threads

The illicit environment used for tracking the current CallId is thread-local, but values used to track slots are interned in a global cache. This means that two different threads calling an identical chain of nested functions can observe identical CallIds:

use std::{
    sync::mpsc::{channel, Sender},
    thread,
};

let (send_ids, recv_ids) = channel();

let spawn_worker = |sender: Sender<(CallId, CallId)>| {
    thread::spawn(move || sender.send(root(returns_two_ids)).unwrap())
};
let first_thread = spawn_worker(send_ids.clone());
let second_thread = spawn_worker(send_ids);

first_thread.join().unwrap();
second_thread.join().unwrap();

// the two worker threads "did the same work"
assert_eq!(recv_ids.recv()?, recv_ids.recv()?);

Implementations

Returns the current CallId.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Call op within the context of a Layer containing self.

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait. Read more

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait. Read more

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s. Read more

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s. Read more

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait. Read more

Performs the conversion.

Performs the conversion.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.